#Part 1 The purpose of this notebook is to determine the selective benefit of glucosinolate and flavonoid compounds through plant competition by creating selection gradients. Selection gradients will involve final body mass as the proxy for fitness, but this will be replaced with fitness once the measurement is in. Concentration will be on the x-axis. This analysis will account for family and greenhouse location.

#Part 2 The second purpose is to determine if glucosinolates and flavonoids influence suscpetibility to pathogens and if this susceptibility results in increased fitness

#Read in and prep data

library(ggplot2)
library(lme4)
#library(tidyr)
library(cowplot)
library(grid)
library(gridExtra)
library(dplyr)
source("GGPlot_Themes.R")

#read in data
rm(list=ls())
dat<-read.csv("DataSynthesis.csv")

#Remove maple controls data from the data set.
dat<-dat %>% filter(treatment!="mcnt") %>% droplevels()

#Assign family column
prefamily<-gsub("*.\\|","",dat$Tag)
dat$Family<-gsub("\\-.*","",prefamily)

#remove those with fertilizer treatment, and extra genotypes that are only in the alone treatment. 
dat<-dat[!grepl("i",dat$Sample,fixed=T),]

#Initializing columns to avoid constant error messages. 
dat$WhiteFungLogis<-NA
dat$BlackFungLogis<-NA

#Generating data frames with summarized leaf data (dat2) and summarized genotype data (dat3)


#Logging data
dat$Fern<-log(dat$Fern+1)
dat$gluc_Conc<-log(dat$gluc_Conc)
dat$flav_Conc<-log(dat$flav_Conc)
dat$ChlorA<-log(dat$ChlorA)
NaNs produced
dat$ThripsDam<-log(dat$ThripsDam+1)
dat$BlackPathDam<-log(dat$BlackPathDam+1)


#Creating leaf area vector 
dat$GM_Leaf_Area<-dat$GM_Leaf_Len*dat$GM_Leaf_Wid


#Summarizing: Taking the mean value of leaves. This tibble contains data at the level of the plant means. 
dat2<-dat %>% group_by(Tag) %>% summarize(ChlorA=mean(ChlorA),ChlorB=mean(ChlorB),gluc_Conc=mean(gluc_Conc),flav_Conc=mean(flav_Conc),Family=first(Family),treatment=first(treatment),gh_row=first(gh_row),gh_bench=first(gh_bench),GM_TotalLeaf_Area=first(GM_TotalLeaf_Area),comp_number=first(comp_number),ThripsDam=mean(ThripsDam),WhiteFungDam=mean(WhiteFungDam),BlackPathDam=mean(BlackPathDam),Fern=mean(Fern),gh_col=first(gh_col),GM_Leaf_Area=mean(GM_Leaf_Area))

#All of these genotypes died (15 Genotypes).(We are simply missing a final measurement for e|JBCHY1-1-50|Q|240) That is only 3% Mortality. 
dead<-dat2[is.na(dat2$GM_TotalLeaf_Area),]

#Removing those with dead competitors from the garlic mustard treatment. ("e|JBCHY1-1-50|Q|240") did not die, we are simply missing the final measurement for it.

dead_competitors<-dead %>% filter(treatment=="gm",Tag!="e|JBCHY1-1-50|Q|240") %>% select(comp_number)

#Removing those with dead competitors from the analysis. 
dat2<-dat2 %>% filter(!comp_number %in% dead_competitors$comp_number)
dat<-dat %>% filter(!comp_number %in% dead_competitors$comp_number)


##Summarizing: Taking the mean value of plants. This tibble contains data at the level of the family means within each treatment. 
dat3<-dat2 %>% drop_na(GM_TotalLeaf_Area) %>% group_by(Family,treatment)  %>% summarize_if(is.numeric,mean)



#Because of how zero inflated white pathogen damage is, i will use a logistic regression to model it.
dat2$WhiteFungLogis<-NA
dat2$WhiteFungLogis[dat2$WhiteFungDam==0]<-0
dat2$WhiteFungLogis[dat2$WhiteFungDam>0]<-1

#Searching for a fitness trade-off between the alone and interspecific competition treatment.

source("GGPlot_Themes.R")

#Calculating family means within treatment. 
TradeOff<-dat3 %>% filter(treatment=="a") %>% drop_na(GM_TotalLeaf_Area) %>%  select(LeafSizeAlone=GM_TotalLeaf_Area,Family,gluc_ConcAlone=gluc_Conc) %>% right_join(dat3 %>% filter(treatment=="m") %>%  select(LeafSizeMaple=GM_TotalLeaf_Area,Family,gluc_ConcMaple=gluc_Conc),by="Family")

#Calculating standard error of each family
StdErr<-dat2 %>% select(Family,treatment,GM_TotalLeaf_Area) %>% group_by(Family,treatment) %>% drop_na(GM_TotalLeaf_Area) %>%  summarize(StdErr=sd(GM_TotalLeaf_Area)/sqrt(length(GM_TotalLeaf_Area)),size=length(GM_TotalLeaf_Area))

#Shifting the data to be in long form. 
StdErr2<-StdErr %>% filter(treatment=="a") %>% select(StdErrAlone=StdErr,Family) %>% right_join(StdErr %>% filter(treatment=="m") %>% select(StdErrMaple=StdErr,Family),by="Family")

TradeOff2<-StdErr2 %>% left_join(TradeOff)
Joining, by = "Family"
#tiff("Selection_Figures/TradeOff.tiff", units="in", width=10, height=6, res=300)

ggplot(TradeOff2,aes(y=LeafSizeAlone,x=LeafSizeMaple))+
  geom_point()+
  geom_linerange(aes(ymin = LeafSizeAlone - StdErrAlone, 
                    ymax = LeafSizeAlone + StdErrAlone))+
  geom_errorbarh(aes(xmin = LeafSizeMaple - StdErrMaple,
                    xmax = LeafSizeMaple + StdErrMaple))+
theme_simple()+
  xlab("Performance with Maple")+
  ylab("Performance Alone")

#dev.off()
summary(lm(LeafSizeAlone~LeafSizeMaple,data=TradeOff2))

Call:
lm(formula = LeafSizeAlone ~ LeafSizeMaple, data = TradeOff2)

Residuals:
    Min      1Q  Median      3Q     Max 
-2019.5  -657.0  -265.5   907.7  2364.0 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)   9590.03571 1616.26626   5.933 6.87e-06 ***
LeafSizeMaple   -0.00936    0.18258  -0.051     0.96    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1244 on 21 degrees of freedom
Multiple R-squared:  0.0001251, Adjusted R-squared:  -0.04749 
F-statistic: 0.002628 on 1 and 21 DF,  p-value: 0.9596

#Visualizing genetic variation and greenhouse variation, which will be controlled for.

#GH Bench
ggplot(dat2)+
  geom_point(aes(y=gluc_Conc,x=gh_bench,colour=as.factor(gh_bench)))


#GH Col
ggplot(dat2)+
  geom_point(aes(y=gluc_Conc,x=gh_col,colour=as.factor(gh_bench)))


#Investigating genetic differences by treatment
#gluc_Conc
boxplot(gluc_Conc~Family,data=dat2[dat2$treatment=="a",])

boxplot(gluc_Conc~Family,data=dat2[dat2$treatment=="m",])

boxplot(gluc_Conc~Family,data=dat2[dat2$treatment=="gm",])

#bodymass
boxplot(GM_TotalLeaf_Area~Family,data=dat2[dat2$treatment=="a",])

boxplot(GM_TotalLeaf_Area~Family,data=dat2[dat2$treatment=="m",])

boxplot(GM_TotalLeaf_Area~Family,data=dat2[dat2$treatment=="gm",])

#What influences performance? New model without gluc flav

summary(fit6) #This is a much cleaner result than using three different models for each treatment. I think instead i will use this model to assess pathogen damage. and i will determine the effect that the size of the maple has in the maple analysis. 
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
GM_TotalLeaf_Area ~ treatment + BlackPathDam + WhiteFungLogis +  
    ThripsDam + GM_Leaf_Area + (1 | gh_bench) + (1 | Family)
   Data: dat2

REML criterion at convergence: 7984.3

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.3919 -0.6053 -0.0053  0.5619  3.8123 

Random effects:
 Groups   Name        Variance Std.Dev.
 Family   (Intercept)  337263   580.7  
 gh_bench (Intercept)  395515   628.9  
 Residual             5196413  2279.6  
Number of obs: 440, groups:  Family, 23; gh_bench, 5

Fixed effects:
               Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)     9733.05     407.19     7.61  23.903 1.95e-08 ***
treatmentgm    -2307.76     313.00   421.17  -7.373 8.92e-13 ***
treatmentm     -1123.98     270.07   412.01  -4.162 3.85e-05 ***
BlackPathDam    -955.83     172.11   427.56  -5.554 4.93e-08 ***
WhiteFungLogis  -609.25     256.84   428.46  -2.372   0.0181 *  
ThripsDam       -281.51     151.94   430.96  -1.853   0.0646 .  
GM_Leaf_Area    1744.43     139.88   431.25  12.471  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) trtmntg trtmntm BlckPD WhtFnL ThrpsD
treatmentgm -0.277                                     
treatmentm  -0.353  0.447                              
BlackPathDm -0.184 -0.037   0.025                      
WhiteFngLgs -0.200  0.054   0.119  -0.022              
ThripsDam   -0.253 -0.237  -0.032   0.021 -0.012       
GM_Leaf_Are -0.035  0.457   0.042  -0.010 -0.043 -0.288

#Model Diagnostics.

#Is there a cost to glucosinolate production?

summary(fit6) #As are flavonoids. 
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: 
GM_TotalLeaf_Area ~ treatment + BlackPathDam + WhiteFungLogis +  
    ThripsDam + GM_Leaf_Area + flav_Conc + (1 | Family) + (1 |  
    gh_bench)
   Data: dat2

REML criterion at convergence: 6273.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.4264 -0.5954  0.0449  0.6186  3.5043 

Random effects:
 Groups   Name        Variance Std.Dev.
 Family   (Intercept)  268511   518.2  
 gh_bench (Intercept)  561259   749.2  
 Residual             5418151  2327.7  
Number of obs: 347, groups:  Family, 23; gh_bench, 5

Fixed effects:
                Estimate Std. Error        df t value Pr(>|t|)    
(Intercept)    10014.241    476.587     7.425  21.012 6.93e-08 ***
treatmentgm    -1953.425    374.641   332.928  -5.214 3.25e-07 ***
treatmentm      -972.699    313.930   324.675  -3.098 0.002115 ** 
BlackPathDam    -870.632    197.491   335.056  -4.408 1.40e-05 ***
WhiteFungLogis  -585.477    293.544   332.437  -1.995 0.046912 *  
ThripsDam       -232.612    173.556   335.843  -1.340 0.181064    
GM_Leaf_Area    1830.260    157.673   338.907  11.608  < 2e-16 ***
flav_Conc       2786.414    744.882   338.626   3.741 0.000215 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) trtmntg trtmntm BlckPD WhtFnL ThrpsD GM_L_A
treatmentgm -0.223                                            
treatmentm  -0.325  0.454                                     
BlackPathDm -0.169 -0.050   0.049                             
WhiteFngLgs -0.188  0.048   0.134  -0.046                     
ThripsDam   -0.225 -0.204  -0.001   0.063 -0.014              
GM_Leaf_Are -0.011  0.470   0.065  -0.034 -0.041 -0.301       
flav_Conc    0.158  0.210   0.151   0.088  0.035  0.162  0.087

#Visualization – The conditional benefit of glucosinolates (allelopathy)


aloneSlope<-function(x){
  y=-3966.60*x+ 13751.96
  return(y)
}
mapleSlope<-function(x){
  y=(-4254.2+8417.95)*x+13751.96 -9243.71
  return(y)
}

mustardSlope<-function(x){
  y=+13751.96-8376.67#Non significant slope
  return(y)
}

minM<-min(dat2$gluc_Conc[dat2$treatment=="m"],na.rm = T)
maxM<-max(dat2$gluc_Conc[dat2$treatment=="m"],na.rm = T)

minA<-min(dat2$gluc_Conc[dat2$treatment=="a"],na.rm = T)
maxA<-max(dat2$gluc_Conc[dat2$treatment=="a"],na.rm = T)

minG<-min(dat2$gluc_Conc[dat2$treatment=="gm"],na.rm = T)
maxG<-max(dat2$gluc_Conc[dat2$treatment=="gm"],na.rm = T)

#tiff("Selection_Figures/Gluc_Benefit.tiff", units="in", width=10, height=6, res=300)
library(ggplot2)
ggplot(dat2)+
  geom_point(aes(y=GM_TotalLeaf_Area,x=gluc_Conc,colour=treatment),size=2)+
  geom_segment(x=minA,xend=maxA,y=aloneSlope(minA),yend=aloneSlope(maxA),colour="#009E73",size=1.5)+
    geom_segment(x=minM,xend=maxM,y=mapleSlope(minM),yend=mapleSlope(maxM),colour="#E69F00",size=1.5)+
  geom_segment(x=minG,xend=maxG,y=mustardSlope(minG),yend=mustardSlope(maxG),colour="#56B4E9",size=1.5)+theme_simple()+
  ylab(bquote(bold("Performance\n(Total Leaf Area "~(mm^2)~")")))+xlab(bquote(bold("[Total Glucosinolate] " (mg/ml))))+
  scale_colour_manual(values=c("#009E73","#56B4E9","#E69F00"),labels=c("Alone","Garlic Mustard","Maple"))

#dev.off()

minA
[1] 0.7713421

#Visualizing the effect of flavonoid on fitness.

summary(lmer(GM_TotalLeaf_Area~treatment+flav_Conc+BlackPathDam+Fern+(1|Family)+(1|gh_bench/gh_col), data=dat2))
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: GM_TotalLeaf_Area ~ treatment + flav_Conc + BlackPathDam + Fern +  
    (1 | Family) + (1 | gh_bench/gh_col)
   Data: dat2

REML criterion at convergence: 6473.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.1990 -0.6278  0.0560  0.6004  2.6495 

Random effects:
 Groups          Name        Variance Std.Dev.
 gh_col:gh_bench (Intercept)  660632   812.8  
 Family          (Intercept)  210327   458.6  
 gh_bench        (Intercept) 1767108  1329.3  
 Residual                    7165525  2676.8  
Number of obs: 350, groups:  gh_col:gh_bench, 28; Family, 23; gh_bench, 5

Fixed effects:
             Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)   7682.44    1156.80    33.30   6.641 1.42e-07 ***
treatmentgm  -3897.18     385.80   333.76 -10.102  < 2e-16 ***
treatmentm   -1133.35     364.02   330.79  -3.113  0.00201 ** 
flav_Conc     2471.19    1040.31   341.75   2.375  0.01808 *  
BlackPathDam   -77.69      30.19   335.79  -2.573  0.01050 *  
Fern          -125.75      57.56   330.33  -2.185  0.02962 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) trtmntg trtmntm flv_Cn BlckPD
treatmentgm -0.294                              
treatmentm  -0.260  0.475                       
flav_Conc   -0.795  0.198   0.137               
BlackPathDm -0.163 -0.043   0.021   0.090       
Fern        -0.035 -0.037  -0.073   0.030 -0.156
aloneSlope<-function(x){
  y=2024.62 *x+  8035.30
  return(y)
}
mapleSlope<-function(x){
  y=(2024.62 )*x+ 8035.30 -1067.02
  return(y)
}

mustardSlope<-function(x){
  y=2024.62 *x+ 8035.30-3746.91#Non significant slope
  return(y)
}

minM<-min(dat2$flav_Conc[dat2$treatment=="m"],na.rm = T)
maxM<-max(dat2$flav_Conc[dat2$treatment=="m"],na.rm = T)

minA<-min(dat2$flav_Conc[dat2$treatment=="a"],na.rm = T)
maxA<-max(dat2$flav_Conc[dat2$treatment=="a"],na.rm = T)

minG<-min(dat2$flav_Conc[dat2$treatment=="gm"],na.rm = T)
maxG<-max(dat2$flav_Conc[dat2$treatment=="gm"],na.rm = T)


#tiff("Selection_Figures/Flav_Benefit.tiff", units="in", width=10, height=6, res=300)
ggplot(dat2)+
  geom_point(aes(y=GM_TotalLeaf_Area,x=flav_Conc,colour=treatment),size=2)+
  geom_segment(x=minA,xend=maxA,y=aloneSlope(minA),yend=aloneSlope(maxA),colour="#009E73",size=1.5)+
    geom_segment(x=minM,xend=maxM,y=mapleSlope(minM),yend=mapleSlope(maxM),colour="#E69F00",size=1.5)+theme_simple()+
  geom_segment(x=minG,xend=maxG,y=mustardSlope(minG),yend=mustardSlope(maxG),colour="#56B4E9",size=1.5)+theme_simple()+
  ylab(bquote(bold("Performance\n(Total Leaf Area "~(mm^2)~")")))+xlab(bquote(bold("[Total Flavonoid] " (mg/ml))))+
  scale_colour_manual(values=c("#009E73","#56B4E9","#E69F00"),labels=c("Alone","Garlic Mustard","Maple"))

#dev.off()

#Visualization– The Detriment of pathogens and ferns

summary(lmer(GM_TotalLeaf_Area ~ Fern+
(1 | Family) + (1 | gh_bench/gh_col) ,data=dat2))
boundary (singular) fit: see ?isSingular
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: GM_TotalLeaf_Area ~ Fern + (1 | Family) + (1 | gh_bench/gh_col)
   Data: dat2

REML criterion at convergence: 9607.6

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-2.85397 -0.70508  0.04291  0.74619  3.11787 

Random effects:
 Groups          Name        Variance Std.Dev.
 gh_col:gh_bench (Intercept)    96624  310.8  
 Family          (Intercept)        0    0.0  
 gh_bench        (Intercept)  2947085 1716.7  
 Residual                    10094168 3177.1  
Number of obs: 507, groups:  gh_col:gh_bench, 28; Family, 23; gh_bench, 5

Fixed effects:
            Estimate Std. Error       df t value Pr(>|t|)    
(Intercept) 7896.911    807.136    4.071   9.784 0.000561 ***
Fern        -226.020     56.097  432.082  -4.029 6.61e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
     (Intr)
Fern -0.055
convergence code: 0
boundary (singular) fit: see ?isSingular
a<-ggplot(dat2)+
  geom_point(aes(y=GM_TotalLeaf_Area,x=BlackPathDam))+theme_simple_multiCol()+
  geom_abline(intercept=8281.76,slope = -105.28,size=1.5)+
  xlab("Black Pathogen Damage")

b<-ggplot(dat2[dat2$WhiteFungDam<30,])+
  geom_point(aes(y=GM_TotalLeaf_Area,x=WhiteFungDam),colour="#999999")+theme_simple_multiCol()+
  theme(axis.title.x = element_text(color = "#999999", size = 16, face = "bold",margin=margin(3,0,3,0)),
      )+xlab("Powdery Mildew Damage")

c<-ggplot(dat2)+
  geom_point(aes(y=GM_TotalLeaf_Area,x=ThripsDam),colour="#E69F00")+theme_simple_multiCol()+xlab("Thrips Damage")+
    theme(axis.title.x = element_text(color = "#E69F00", size = 16, face = "bold",margin=margin(3,0,3,0)))

d<-ggplot(dat2)+
  geom_point(aes(y=GM_TotalLeaf_Area,x=Fern),colour="#009E73")+theme_simple_multiCol()+xlab("Fern Abundance")+
   geom_abline(intercept=8003.44,slope = -179.47,size=1.5,color="#009E73")+
  theme(axis.title.x = element_text(color = "#009E73", size = 16, face = "bold",margin=margin(3,0,3,0)))
   


plot<-plot_grid(a, b,ncol=2,rel_widths = c(1,1))
Removed 61 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).
plot2<-plot_grid(d, c,ncol=2,rel_widths = c(1,1))
Removed 9 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).
plot3<-plot_grid(a,b,c,d,ncol=2,rel_widths = c(1,1))
Removed 61 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).Removed 9 rows containing missing values (geom_point).
plot4<-plot_grid(a,b,c,ncol=1,rel_widths = c(1,1,1))
Removed 61 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).
plot5<-plot_grid(a,b,c,ncol=3,rel_widths = c(1,1,1))
Removed 61 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).Removed 61 rows containing missing values (geom_point).
y.grob<-textGrob(bquote(bold("Shoot Area "(mm^2))),gp=gpar(fontface="bold",fontsize=20),rot=90)


#tiff("Selection_Figures/PathogenEffect.tiff", units="in", width=14, height=6, res=300)
grid.arrange(plot,left=y.grob)

#dev.off()

#tiff("Selection_Figures/PathogenEffect2.tiff", units="in", width=14, height=6, res=300)
grid.arrange(plot2,left=y.grob)

#dev.off()

#tiff("Selection_Figures/PathogenEffect3.tiff", units="in", width=14, height=10, res=300)
grid.arrange(plot3,left=y.grob)

#dev.off

grid.arrange(plot4,left=y.grob)



#tiff("Selection_Figures/PathogenEffect5.tiff", units="in", width=16, height=5, res=300)
grid.arrange(plot5,left=y.grob)

#dev.off

#tiff("Selection_Figures/FernEffect.tiff", units="in", width=8, height=6, res=300)
grid.arrange(d,left=y.grob)

#dev.off

#—————————————– #Part 2

#Influence of gluc and flav on defence.

hist(dat$Fern)
Warning messages:
1: Unknown or uninitialised column: `WhiteFungLogis`. 
2: Unknown or uninitialised column: `WhiteFungLogis`. 
3: Unknown or uninitialised column: `WhiteFungLogis`. 
4: Unknown or uninitialised column: `WhiteFungLogis`. 
5: Unknown or uninitialised column: `WhiteFungLogis`. 
6: Unknown or uninitialised column: `WhiteFungLogis`. 
7: Unknown or uninitialised column: `WhiteFungLogis`. 
8: Unknown or uninitialised column: `WhiteFungLogis`. 
9: Unknown or uninitialised column: `WhiteFungLogis`. 
10: Unknown or uninitialised column: `WhiteFungLogis`. 

#Modelling : Negative binomial on Thrips Damage.

summary(fit_g)$coef
$cond
             Estimate Std. Error   z value     Pr(>|z|)
(Intercept)  3.585466  0.5478174  6.545002 5.949477e-11
gluc_Conc   -2.793644  0.5756398 -4.853111 1.215394e-06

$zi
NULL

$disp
NULL

#Visualize: Thrips Damage predicted by glucosinolates and flavonoids


source("GGPlot_Themes.R")
Warning messages:
1: Unknown or uninitialised column: `WhiteFungLogis`. 
2: Unknown or uninitialised column: `WhiteFungLogis`. 
3: Unknown or uninitialised column: `WhiteFungLogis`. 
4: Unknown or uninitialised column: `WhiteFungLogis`. 
#Reversing link function, to estimate the data on the response scale. 
flavSlope=function(x){
  y=exp(-2.4621 *x+2.9746)
  return(y)
}
glucSlope=function(x){
  y=exp(-2.7869*x+3.5755)
  return(y)
}

#Determining x range to fit the line to 
flavplot=seq(min(dat$flav_Conc,na.rm = T),max(dat$flav_Conc,na.rm=T),length.out = 688)
glucplot=seq(min(dat$gluc_Conc,na.rm = T),max(dat$gluc_Conc,na.rm=T),length.out = 708)

#Calculating slope values
flavy<-flavSlope(flavplot)
glucy<-glucSlope(glucplot)


#tiff("Defence_Figures/FlavonoidThrips.tiff", units="in", width=10, height=6, res=300)
ggplot(dat[!is.na(dat$flav_Conc),])+
  geom_point(aes(y=ThripsDam,x=flav_Conc))+theme_simple()+
  geom_path(x=flavplot,y=flavy,size=1,colour="#999999")+
  
  scale_y_continuous(breaks=seq(0,70,5))+
  ylab("Thrips Damage")+
xlab(bquote(bold("[Total Flavonoid] " (mg/ml))))

#dev.off()

ggplot(dat[!is.na(dat$gluc_Conc),])+
  geom_point(aes(y=ThripsDam,x=gluc_Conc))+theme_simple()+
  geom_path(x=glucplot,y=glucy,size=1,colour="#999999")+
  
  scale_y_continuous(breaks=seq(0,70,5))+
  ylab("Thrips Damage")+
xlab(bquote(bold("[Total Glucosinolate] " (mg/ml))))

I think that a logistic regression is more appropriate for fungal abundance, because the count of fungal infection could be arbuitrary, especially when fungal patches were large or the leaf was completely covered.

#WhitePathDam – logistic regression

summary(fit.4) #Garlic mustard in the maple treatment have less occurence of fungal colonization. 
Generalized linear mixed model fit by maximum likelihood (Laplace
  Approximation) [glmerMod]
 Family: binomial  ( logit )
Formula: WhiteFungLogis ~ treatment + (1 | Family)
   Data: dat2

     AIC      BIC   logLik deviance df.resid 
   519.2    535.7   -255.6    511.2      451 

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.3885 -0.6239 -0.4587  0.9947  3.3329 

Random effects:
 Groups Name        Variance Std.Dev.
 Family (Intercept) 0.544    0.7376  
Number of obs: 455, groups:  Family, 23

Fixed effects:
            Estimate Std. Error z value Pr(>|z|)   
(Intercept)  -0.6835     0.2395  -2.854  0.00431 **
treatmentgm  -0.4101     0.2613  -1.569  0.11656   
treatmentm   -0.8037     0.2756  -2.916  0.00355 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) trtmntg
treatmentgm -0.509        
treatmentm  -0.474  0.447 

#Visualizing – effect of treatment on proportion of fungal abundance.

#Modelling: Negative Binomial – BlackPathDam

fit_2<-glmmTMB(BlackPathDam~treatment+flav_Conc+(1|Family/Tag),family=nbinom2,data=dat)
fit_2<-glmmTMB(BlackPathDam~treatment+flav_Conc+(1|Family/Tag),family=nbinom2,data=dat)
summary(fit_2)
 Family: nbinom2  ( log )
Formula:          BlackPathDam ~ treatment + flav_Conc + (1 | Family/Tag)
Data: dat

     AIC      BIC   logLik deviance df.resid 
  1822.7   1854.3   -904.3   1808.7      669 

Random effects:

Conditional model:
 Groups     Name        Variance Std.Dev.
 Tag:Family (Intercept) 1.4410   1.2004  
 Family     (Intercept) 0.2517   0.5017  
Number of obs: 676, groups:  Tag:Family, 423; Family, 23

Overdispersion parameter for nbinom2 family (): 0.641 

Conditional model:
            Estimate Std. Error z value Pr(>|z|)   
(Intercept)   0.7826     0.4876   1.605   0.1085   
treatmentgm   0.1049     0.2480   0.423   0.6724   
treatmentm   -0.5204     0.2500  -2.082   0.0374 * 
flav_Conc    -1.5060     0.5172  -2.912   0.0036 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

#Visualizing: The effect of treatment and flavonoid abundance on black pathogen abundance.

#Visualization – Black pathogen damage by treatment


plot2<-dat2 %>% drop_na(BlackPathDam) %>% group_by(treatment) %>% summarize(BlackPathAve=mean(BlackPathDam,na.rm=T))

ggplot(plot2)+
  geom_col(aes(x=treatment,y=BlackPathAve,fill=treatment))+theme_simple()+ylab("Black Pathogen Infection\n(spots/leaf)")+xlab("Treatment")+theme(legend.position = "none")

#Modelling: Negative Binomial- Fern abundance

summary(fit_1)
 Family: nbinom2  ( log )
Formula:          Fern ~ treatment + (1 | gh_bench)
Data: datFern

     AIC      BIC   logLik deviance df.resid 
   766.3    787.6   -378.2    756.3      511 

Random effects:

Conditional model:
 Groups   Name        Variance Std.Dev.
 gh_bench (Intercept) 1.803    1.343   
Number of obs: 516, groups:  gh_bench, 5

Overdispersion parameter for nbinom2 family (): 0.0905 

Conditional model:
            Estimate Std. Error z value Pr(>|z|)  
(Intercept)  -1.5550     0.7070  -2.199   0.0279 *
treatmentgm   1.1243     0.5038   2.232   0.0256 *
treatmentm    0.9924     0.4285   2.316   0.0205 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Warning messages:
1: Unknown or uninitialised column: `WhiteFungLogis`. 
2: Unknown or uninitialised column: `WhiteFungLogis`. 
3: Unknown or uninitialised column: `WhiteFungLogis`. 
4: Unknown or uninitialised column: `WhiteFungLogis`. 

#Visualizing — the distribution of pathogens by treatment.

#Visualizing – effect of flavonoids on fern abundance.


PoisSlope=function(x,int){
  y=exp((-0.02353 -3.12475)*x+int)
  return(y)
}
exp(-0.6571)

flavplot=seq(min(dat$flav_Conc,na.rm = T),max(dat$flav_Conc,na.rm=T),length.out = 707)

flavyA<-PoisSlope(flavplot,-2.1683)
flavyM<-PoisSlope(flavplot,-1.60546-2.81450)
flavyGM<-PoisSlope(flavplot,-2.1683-0.2786)


#tiff("Defence_Figures/FlavonoidFern.tiff", units="in", width=10, height=6, res=300)
ggplot(dat)+
  geom_point(aes(y=Fern,x=flav_Conc,colour=treatment))+theme_simple()+
 # geom_path(x=flavplot,y=flavyA,size=1,colour="#009E73")
  #geom_path(x=flavplot,y=flavyGM,size=1,colour="#56B4E9")
  geom_path(x=flavplot,y=flavyM,size=1,colour="#E69F00")+
      scale_colour_manual(values=c("#009E73","#56B4E9","#E69F00"),labels=c("Alone","Garlic Mustard","Maple"))+
  scale_y_continuous(breaks=c(0,5,10,15,20,25,30,35,40))+
  ylab("Fern Abundance")+
xlab(bquote(bold("[Total Flavonoid] " (mg/ml))))
#dev.off()

How can we know that healthy plants dont just exhibit more secondary compounds and not that those with more secondary compounds are healthier?

LS0tCnRpdGxlOiAiU2VsZWN0aXZlIGJlbmVmaXQgb2YgR2x1Y29zaW5vbGF0ZSBhbmQgZmxhdm9ub2lkcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojUGFydCAxClRoZSBwdXJwb3NlIG9mIHRoaXMgbm90ZWJvb2sgaXMgdG8gZGV0ZXJtaW5lIHRoZSBzZWxlY3RpdmUgYmVuZWZpdCBvZiBnbHVjb3Npbm9sYXRlIGFuZCBmbGF2b25vaWQgY29tcG91bmRzIHRocm91Z2ggcGxhbnQgY29tcGV0aXRpb24gYnkgY3JlYXRpbmcgc2VsZWN0aW9uIGdyYWRpZW50cy4gU2VsZWN0aW9uIGdyYWRpZW50cyB3aWxsIGludm9sdmUgZmluYWwgYm9keSBtYXNzIGFzIHRoZSBwcm94eSBmb3IgZml0bmVzcywgYnV0IHRoaXMgd2lsbCBiZSByZXBsYWNlZCB3aXRoIGZpdG5lc3Mgb25jZSB0aGUgbWVhc3VyZW1lbnQgaXMgaW4uIENvbmNlbnRyYXRpb24gd2lsbCBiZSBvbiB0aGUgeC1heGlzLiBUaGlzIGFuYWx5c2lzIHdpbGwgYWNjb3VudCBmb3IgZmFtaWx5IGFuZCBncmVlbmhvdXNlIGxvY2F0aW9uLiAKCiNQYXJ0IDIKVGhlIHNlY29uZCBwdXJwb3NlIGlzIHRvIGRldGVybWluZSBpZiBnbHVjb3Npbm9sYXRlcyBhbmQgZmxhdm9ub2lkcyBpbmZsdWVuY2Ugc3VzY3BldGliaWxpdHkgdG8gcGF0aG9nZW5zIGFuZCBpZiB0aGlzIHN1c2NlcHRpYmlsaXR5IHJlc3VsdHMgaW4gaW5jcmVhc2VkIGZpdG5lc3MKCgoKCiNSZWFkIGluIGFuZCBwcmVwIGRhdGEKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsbWU0KQojbGlicmFyeSh0aWR5cikKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KGdyaWQpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGRwbHlyKQpzb3VyY2UoIkdHUGxvdF9UaGVtZXMuUiIpCgojcmVhZCBpbiBkYXRhCnJtKGxpc3Q9bHMoKSkKZGF0PC1yZWFkLmNzdigiRGF0YVN5bnRoZXNpcy5jc3YiKQoKI1JlbW92ZSBtYXBsZSBjb250cm9scyBkYXRhIGZyb20gdGhlIGRhdGEgc2V0LgpkYXQ8LWRhdCAlPiUgZmlsdGVyKHRyZWF0bWVudCE9Im1jbnQiKSAlPiUgZHJvcGxldmVscygpCgojcmVtb3ZlIHRob3NlIHdpdGggZmVydGlsaXplciB0cmVhdG1lbnQsIGFuZCBleHRyYSBnZW5vdHlwZXMgdGhhdCBhcmUgb25seSBpbiB0aGUgYWxvbmUgdHJlYXRtZW50LiAKZGF0PC1kYXRbIWdyZXBsKCJpIixkYXQkU2FtcGxlLGZpeGVkPVQpLF0KCiNJbml0aWFsaXppbmcgY29sdW1ucyB0byBhdm9pZCBjb25zdGFudCBlcnJvciBtZXNzYWdlcy4gCmRhdCRXaGl0ZUZ1bmdMb2dpczwtTkEKZGF0JEJsYWNrRnVuZ0xvZ2lzPC1OQQpgYGAKCgojR2VuZXJhdGluZyBkYXRhIGZyYW1lcyB3aXRoIHN1bW1hcml6ZWQgbGVhZiBkYXRhIChkYXQyKSBhbmQgc3VtbWFyaXplZCBnZW5vdHlwZSBkYXRhIChkYXQzKQpgYGB7cn0KCiNMb2dnaW5nIGRhdGEKZGF0JEZlcm48LWxvZyhkYXQkRmVybisxKQpkYXQkZ2x1Y19Db25jPC1sb2coZGF0JGdsdWNfQ29uYykKZGF0JGZsYXZfQ29uYzwtbG9nKGRhdCRmbGF2X0NvbmMpCmRhdCRDaGxvckE8LWxvZyhkYXQkQ2hsb3JBKQpkYXQkVGhyaXBzRGFtPC1sb2coZGF0JFRocmlwc0RhbSsxKQpkYXQkQmxhY2tQYXRoRGFtPC1sb2coZGF0JEJsYWNrUGF0aERhbSsxKQoKCiNDcmVhdGluZyBsZWFmIGFyZWEgdmVjdG9yIApkYXQkR01fTGVhZl9BcmVhPC1kYXQkR01fTGVhZl9MZW4qZGF0JEdNX0xlYWZfV2lkCgoKI1N1bW1hcml6aW5nOiBUYWtpbmcgdGhlIG1lYW4gdmFsdWUgb2YgbGVhdmVzLiBUaGlzIHRpYmJsZSBjb250YWlucyBkYXRhIGF0IHRoZSBsZXZlbCBvZiB0aGUgcGxhbnQgbWVhbnMuIApkYXQyPC1kYXQgJT4lIGdyb3VwX2J5KFRhZykgJT4lIHN1bW1hcml6ZShDaGxvckE9bWVhbihDaGxvckEpLENobG9yQj1tZWFuKENobG9yQiksZ2x1Y19Db25jPW1lYW4oZ2x1Y19Db25jKSxmbGF2X0NvbmM9bWVhbihmbGF2X0NvbmMpLEZhbWlseT1maXJzdChGYW1pbHkpLHRyZWF0bWVudD1maXJzdCh0cmVhdG1lbnQpLGdoX3Jvdz1maXJzdChnaF9yb3cpLGdoX2JlbmNoPWZpcnN0KGdoX2JlbmNoKSxHTV9Ub3RhbExlYWZfQXJlYT1maXJzdChHTV9Ub3RhbExlYWZfQXJlYSksY29tcF9udW1iZXI9Zmlyc3QoY29tcF9udW1iZXIpLFRocmlwc0RhbT1tZWFuKFRocmlwc0RhbSksV2hpdGVGdW5nRGFtPW1lYW4oV2hpdGVGdW5nRGFtKSxCbGFja1BhdGhEYW09bWVhbihCbGFja1BhdGhEYW0pLEZlcm49bWVhbihGZXJuKSxnaF9jb2w9Zmlyc3QoZ2hfY29sKSxHTV9MZWFmX0FyZWE9bWVhbihHTV9MZWFmX0FyZWEpKQoKI0FsbCBvZiB0aGVzZSBnZW5vdHlwZXMgZGllZCAoMTUgR2Vub3R5cGVzKS4oV2UgYXJlIHNpbXBseSBtaXNzaW5nIGEgZmluYWwgbWVhc3VyZW1lbnQgZm9yIGV8SkJDSFkxLTEtNTB8UXwyNDApIFRoYXQgaXMgb25seSAzJSBNb3J0YWxpdHkuIApkZWFkPC1kYXQyW2lzLm5hKGRhdDIkR01fVG90YWxMZWFmX0FyZWEpLF0KCiNSZW1vdmluZyB0aG9zZSB3aXRoIGRlYWQgY29tcGV0aXRvcnMgZnJvbSB0aGUgZ2FybGljIG11c3RhcmQgdHJlYXRtZW50LiAoImV8SkJDSFkxLTEtNTB8UXwyNDAiKSBkaWQgbm90IGRpZSwgd2UgYXJlIHNpbXBseSBtaXNzaW5nIHRoZSBmaW5hbCBtZWFzdXJlbWVudCBmb3IgaXQuCgpkZWFkX2NvbXBldGl0b3JzPC1kZWFkICU+JSBmaWx0ZXIodHJlYXRtZW50PT0iZ20iLFRhZyE9ImV8SkJDSFkxLTEtNTB8UXwyNDAiKSAlPiUgc2VsZWN0KGNvbXBfbnVtYmVyKQoKI1JlbW92aW5nIHRob3NlIHdpdGggZGVhZCBjb21wZXRpdG9ycyBmcm9tIHRoZSBhbmFseXNpcy4gCmRhdDI8LWRhdDIgJT4lIGZpbHRlcighY29tcF9udW1iZXIgJWluJSBkZWFkX2NvbXBldGl0b3JzJGNvbXBfbnVtYmVyKQpkYXQ8LWRhdCAlPiUgZmlsdGVyKCFjb21wX251bWJlciAlaW4lIGRlYWRfY29tcGV0aXRvcnMkY29tcF9udW1iZXIpCgoKIyNTdW1tYXJpemluZzogVGFraW5nIHRoZSBtZWFuIHZhbHVlIG9mIHBsYW50cy4gVGhpcyB0aWJibGUgY29udGFpbnMgZGF0YSBhdCB0aGUgbGV2ZWwgb2YgdGhlIGZhbWlseSBtZWFucyB3aXRoaW4gZWFjaCB0cmVhdG1lbnQuIApkYXQzPC1kYXQyICU+JSBkcm9wX25hKEdNX1RvdGFsTGVhZl9BcmVhKSAlPiUgZ3JvdXBfYnkoRmFtaWx5LHRyZWF0bWVudCkgICU+JSBzdW1tYXJpemVfaWYoaXMubnVtZXJpYyxtZWFuKQoKCgojQmVjYXVzZSBvZiBob3cgemVybyBpbmZsYXRlZCB3aGl0ZSBwYXRob2dlbiBkYW1hZ2UgaXMsIGkgd2lsbCB1c2UgYSBsb2dpc3RpYyByZWdyZXNzaW9uIHRvIG1vZGVsIGl0LgpkYXQyJFdoaXRlRnVuZ0xvZ2lzPC1OQQpkYXQyJFdoaXRlRnVuZ0xvZ2lzW2RhdDIkV2hpdGVGdW5nRGFtPT0wXTwtMApkYXQyJFdoaXRlRnVuZ0xvZ2lzW2RhdDIkV2hpdGVGdW5nRGFtPjBdPC0xCgoKICAjRnVuY3Rpb24gdG8gc3RhbmRhcmRpemUgdmFyaWFibGVzLiAKU3RhbmRhcmRpemU8LWZ1bmN0aW9uKHgpewogIHN0YW5kYXJkPC0oeC1tZWFuKHgsbmEucm09VCkpL3NkKHgsbmEucm09VCkKfQoKI1N0YW5kYXJkaXppbmcgbGVhZiBhcmVhLiAKZGF0MiRHTV9MZWFmX0FyZWE8LVN0YW5kYXJkaXplKGRhdDIkR01fTGVhZl9BcmVhKQoKYGBgCgoKI1NlYXJjaGluZyBmb3IgYSBmaXRuZXNzIHRyYWRlLW9mZiBiZXR3ZWVuIHRoZSBhbG9uZSBhbmQgaW50ZXJzcGVjaWZpYyBjb21wZXRpdGlvbiB0cmVhdG1lbnQuIApgYGB7cn0Kc291cmNlKCJHR1Bsb3RfVGhlbWVzLlIiKQoKI0NhbGN1bGF0aW5nIGZhbWlseSBtZWFucyB3aXRoaW4gdHJlYXRtZW50LiAKVHJhZGVPZmY8LWRhdDMgJT4lIGZpbHRlcih0cmVhdG1lbnQ9PSJhIikgJT4lIGRyb3BfbmEoR01fVG90YWxMZWFmX0FyZWEpICU+JSAgc2VsZWN0KExlYWZTaXplQWxvbmU9R01fVG90YWxMZWFmX0FyZWEsRmFtaWx5LGdsdWNfQ29uY0Fsb25lPWdsdWNfQ29uYykgJT4lIHJpZ2h0X2pvaW4oZGF0MyAlPiUgZmlsdGVyKHRyZWF0bWVudD09Im0iKSAlPiUgIHNlbGVjdChMZWFmU2l6ZU1hcGxlPUdNX1RvdGFsTGVhZl9BcmVhLEZhbWlseSxnbHVjX0NvbmNNYXBsZT1nbHVjX0NvbmMpLGJ5PSJGYW1pbHkiKQoKI0NhbGN1bGF0aW5nIHN0YW5kYXJkIGVycm9yIG9mIGVhY2ggZmFtaWx5ClN0ZEVycjwtZGF0MiAlPiUgc2VsZWN0KEZhbWlseSx0cmVhdG1lbnQsR01fVG90YWxMZWFmX0FyZWEpICU+JSBncm91cF9ieShGYW1pbHksdHJlYXRtZW50KSAlPiUgZHJvcF9uYShHTV9Ub3RhbExlYWZfQXJlYSkgJT4lICBzdW1tYXJpemUoU3RkRXJyPXNkKEdNX1RvdGFsTGVhZl9BcmVhKS9zcXJ0KGxlbmd0aChHTV9Ub3RhbExlYWZfQXJlYSkpLHNpemU9bGVuZ3RoKEdNX1RvdGFsTGVhZl9BcmVhKSkKCiNTaGlmdGluZyB0aGUgZGF0YSB0byBiZSBpbiBsb25nIGZvcm0uIApTdGRFcnIyPC1TdGRFcnIgJT4lIGZpbHRlcih0cmVhdG1lbnQ9PSJhIikgJT4lIHNlbGVjdChTdGRFcnJBbG9uZT1TdGRFcnIsRmFtaWx5KSAlPiUgcmlnaHRfam9pbihTdGRFcnIgJT4lIGZpbHRlcih0cmVhdG1lbnQ9PSJtIikgJT4lIHNlbGVjdChTdGRFcnJNYXBsZT1TdGRFcnIsRmFtaWx5KSxieT0iRmFtaWx5IikKClRyYWRlT2ZmMjwtU3RkRXJyMiAlPiUgbGVmdF9qb2luKFRyYWRlT2ZmKQoKCiN0aWZmKCJTZWxlY3Rpb25fRmlndXJlcy9UcmFkZU9mZi50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9MTAsIGhlaWdodD02LCByZXM9MzAwKQoKZ2dwbG90KFRyYWRlT2ZmMixhZXMoeT1MZWFmU2l6ZUFsb25lLHg9TGVhZlNpemVNYXBsZSkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IExlYWZTaXplQWxvbmUgLSBTdGRFcnJBbG9uZSwgCiAgICAgICAgICAgICAgICAgICAgeW1heCA9IExlYWZTaXplQWxvbmUgKyBTdGRFcnJBbG9uZSkpKwogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gTGVhZlNpemVNYXBsZSAtIFN0ZEVyck1hcGxlLAogICAgICAgICAgICAgICAgICAgIHhtYXggPSBMZWFmU2l6ZU1hcGxlICsgU3RkRXJyTWFwbGUpKSsKdGhlbWVfc2ltcGxlKCkrCiAgeGxhYigiUGVyZm9ybWFuY2Ugd2l0aCBNYXBsZSIpKwogIHlsYWIoIlBlcmZvcm1hbmNlIEFsb25lIikKI2Rldi5vZmYoKQpzdW1tYXJ5KGxtKExlYWZTaXplQWxvbmV+TGVhZlNpemVNYXBsZSxkYXRhPVRyYWRlT2ZmMikpCgpgYGAKCgoKCgojVmlzdWFsaXppbmcgZ2VuZXRpYyB2YXJpYXRpb24gYW5kIGdyZWVuaG91c2UgdmFyaWF0aW9uLCB3aGljaCB3aWxsIGJlIGNvbnRyb2xsZWQgZm9yLiAKYGBge3J9CiNHSCBCZW5jaApnZ3Bsb3QoZGF0MikrCiAgZ2VvbV9wb2ludChhZXMoeT1nbHVjX0NvbmMseD1naF9iZW5jaCxjb2xvdXI9YXMuZmFjdG9yKGdoX2JlbmNoKSkpCgojR0ggQ29sCmdncGxvdChkYXQyKSsKICBnZW9tX3BvaW50KGFlcyh5PWdsdWNfQ29uYyx4PWdoX2NvbCxjb2xvdXI9YXMuZmFjdG9yKGdoX2JlbmNoKSkpCgojSW52ZXN0aWdhdGluZyBnZW5ldGljIGRpZmZlcmVuY2VzIGJ5IHRyZWF0bWVudAojZ2x1Y19Db25jCmJveHBsb3QoZ2x1Y19Db25jfkZhbWlseSxkYXRhPWRhdDJbZGF0MiR0cmVhdG1lbnQ9PSJhIixdKQpib3hwbG90KGdsdWNfQ29uY35GYW1pbHksZGF0YT1kYXQyW2RhdDIkdHJlYXRtZW50PT0ibSIsXSkKYm94cGxvdChnbHVjX0NvbmN+RmFtaWx5LGRhdGE9ZGF0MltkYXQyJHRyZWF0bWVudD09ImdtIixdKQojYm9keW1hc3MKYm94cGxvdChHTV9Ub3RhbExlYWZfQXJlYX5GYW1pbHksZGF0YT1kYXQyW2RhdDIkdHJlYXRtZW50PT0iYSIsXSkKYm94cGxvdChHTV9Ub3RhbExlYWZfQXJlYX5GYW1pbHksZGF0YT1kYXQyW2RhdDIkdHJlYXRtZW50PT0ibSIsXSkKYm94cGxvdChHTV9Ub3RhbExlYWZfQXJlYX5GYW1pbHksZGF0YT1kYXQyW2RhdDIkdHJlYXRtZW50PT0iZ20iLF0pCmBgYAoKCgoKI1doYXQgaW5mbHVlbmNlcyBwZXJmb3JtYW5jZT8gTmV3IG1vZGVsIHdpdGhvdXQgZ2x1YyBmbGF2IApgYGB7cn0KbGlicmFyeShsbWVyVGVzdCkKCiNNb2RlbGxpbmcgcmFuZG9tIGVmZmVjdHMuCmZpdGZ1bGw8LWxtZXIoR01fVG90YWxMZWFmX0FyZWF+dHJlYXRtZW50K0JsYWNrUGF0aERhbStXaGl0ZUZ1bmdMb2dpcytUaHJpcHNEYW0rRmVybitHTV9MZWFmX0FyZWErKDF8RmFtaWx5KSsoMXxnaF9iZW5jaCksIGRhdGE9ZGF0MikKCmZpdGZ1bGwxPC1sbWVyKEdNX1RvdGFsTGVhZl9BcmVhfnRyZWF0bWVudCtCbGFja1BhdGhEYW0rV2hpdGVGdW5nTG9naXMrVGhyaXBzRGFtK0Zlcm4rR01fTGVhZl9BcmVhKygxfEZhbWlseSksIGRhdGE9ZGF0MikKCmZpdGZ1bGwyPC1sbWVyKEdNX1RvdGFsTGVhZl9BcmVhfnRyZWF0bWVudCtCbGFja1BhdGhEYW0rV2hpdGVGdW5nTG9naXMrVGhyaXBzRGFtK0Zlcm4rR01fTGVhZl9BcmVhKygxfGdoX2JlbmNoKSwgZGF0YT1kYXQyKQoKZml0ZnVsbDM8LWxtZXIoR01fVG90YWxMZWFmX0FyZWF+dHJlYXRtZW50K0JsYWNrUGF0aERhbStXaGl0ZUZ1bmdMb2dpcytUaHJpcHNEYW0rRmVybitHTV9MZWFmX0FyZWErKDF8Z2hfYmVuY2gpKygxfEZhbWlseTp0cmVhdG1lbnQpLCBkYXRhPWRhdDIpCgpmaXRmdWxsNDwtbG1lcihHTV9Ub3RhbExlYWZfQXJlYX50cmVhdG1lbnQrQmxhY2tQYXRoRGFtK1doaXRlRnVuZ0xvZ2lzK1Rocmlwc0RhbStGZXJuK0dNX0xlYWZfQXJlYSsoMXxnaF9iZW5jaCkrKDF8RmFtaWx5L3RyZWF0bWVudCksIGRhdGE9ZGF0MikKCiNJcyBmYW1pbHkgaW1wb3J0YW50PyAKYW5vdmEoZml0ZnVsbCxmaXRmdWxsMikgI1llcywgZmFtaWx5IHByZWRpY3RzIHBlcmZvcm1hbmNlLiAKI0lzIGdoIGJlbmNoIGltcG9ydGFudD8gCmFub3ZhKGZpdGZ1bGwsZml0ZnVsbDEpICNZZXMsIGdoX2JlbmNoIHByZWRpY3RzIHBlcmZvcm1hbmNlLiAKI0lzIHRoZXJlIGEgR3hFIGludGVyYWN0aW9uPyAKYW5vdmEoZml0ZnVsbCxmaXRmdWxsMykgCmFub3ZhKGZpdGZ1bGwsZml0ZnVsbDQpICNObyB0aGVyZSBkb2VzIG5vdCBhcHBlYXIgdG8gYmUuIAoKI01vZGVsbGluZyBmaXhlZCBlZmZlY3RzLiAKZml0PC1sbWVyKEdNX1RvdGFsTGVhZl9BcmVhfnRyZWF0bWVudCtCbGFja1BhdGhEYW0qV2hpdGVGdW5nTG9naXMqVGhyaXBzRGFtK0Zlcm4rR01fTGVhZl9BcmVhKygxfEZhbWlseSkrKDF8Z2hfYmVuY2gpLCBkYXRhPWRhdDIpCgpmaXQyPC11cGRhdGUoZml0LH4uLVRocmlwc0RhbTpCbGFja1BhdGhEYW06V2hpdGVGdW5nTG9naXMpCmFub3ZhKGZpdCxmaXQyKSAjTm90IGEgc2lnbmlmaWNhbnQgdGhyZWUgd2F5IGludGVyYWN0aW9uLgoKZml0MzwtdXBkYXRlKGZpdDIsfi4tQmxhY2tQYXRoRGFtOldoaXRlRnVuZ0xvZ2lzKQphbm92YShmaXQzLGZpdDIpICNUaGVyZSBpcyBub3QgYSBzaWduaWZpY2FudCB0d28gd2F5IGludGVyYWN0aW9uLCAKCmZpdDQ8LXVwZGF0ZShmaXQzLH4uLUJsYWNrUGF0aERhbTpUaHJpcHNEYW0pCmFub3ZhKGZpdDQsZml0MykKI1RoZXJlIGlzIG5vdCBhIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gYmxhY2sgcGF0aCBkYW0gYW5kIHRocmlwcyBkYW0uIAoKZml0NTwtdXBkYXRlKGZpdDQsfi4tV2hpdGVGdW5nTG9naXM6VGhyaXBzRGFtKQphbm92YShmaXQ1LGZpdDQpICNUaGVyZSBpcyBub3QgYSBzaWduaWZpY2FudCB3aGl0ZWZ1bmcgZGFtIGFuZCB0aHJpcHMgZGFtIGludGVyYWN0aW9uLiAKCnN1bW1hcnkoZml0NSkKCiNGZXJuIGlzIG5vdCBzaWduaWZpY2FudC4gCmZpdDY8LWxtZXIoR01fVG90YWxMZWFmX0FyZWF+dHJlYXRtZW50K0JsYWNrUGF0aERhbStXaGl0ZUZ1bmdMb2dpcytUaHJpcHNEYW0rR01fTGVhZl9BcmVhKygxfEZhbWlseSkrKDF8Z2hfYmVuY2gpLCBkYXRhPWRhdDIpCgpmaXQ2PC1sbWVyKEdNX1RvdGFsTGVhZl9BcmVhfnRyZWF0bWVudCtCbGFja1BhdGhEYW0rV2hpdGVGdW5nTG9naXMrVGhyaXBzRGFtK0dNX0xlYWZfQXJlYSsoMXxnaF9iZW5jaCkrKDF8RmFtaWx5KSwgZGF0YT1kYXQyKQoKc3VtbWFyeShmaXQ2KSAjVGhpcyBpcyBhIG11Y2ggY2xlYW5lciByZXN1bHQgdGhhbiB1c2luZyB0aHJlZSBkaWZmZXJlbnQgbW9kZWxzIGZvciBlYWNoIHRyZWF0bWVudC4gSSB0aGluayBpbnN0ZWFkIGkgd2lsbCB1c2UgdGhpcyBtb2RlbCB0byBhc3Nlc3MgcGF0aG9nZW4gZGFtYWdlLiBhbmQgaSB3aWxsIGRldGVybWluZSB0aGUgZWZmZWN0IHRoYXQgdGhlIHNpemUgb2YgdGhlIG1hcGxlIGhhcyBpbiB0aGUgbWFwbGUgYW5hbHlzaXMuIAojUGVyY2VudCB2YXJpYW5jZSBleHBsYWluZWQ6IAozMzcyNjMvICggMzk1NTE1ICsgNTE5NjQxMyszMzcyNjMgKQoKI0RvZXMgZmVybiBhZmZlY3QgcGVyZm9ybWFuY2Ugd2l0aG91dCBhY2NvdW50aW5nIGZvciBsZWFmIGFyZWEgKGl0IGlzIG5vdCBhZmZlY3RlZCBieSBsZWFmIGFyZWEpCmZpdDc8LWxtZXIoR01fVG90YWxMZWFmX0FyZWF+dHJlYXRtZW50K0Zlcm4rKDF8RmFtaWx5KSsoMXxnaF9iZW5jaCksIGRhdGE9ZGF0MikKc3VtbWFyeShmaXQ3KSAjV2l0aG91dCBhY2NvdW50IGZvciBsZWFmIGFyZWEsIGZlcm4gaXMgYSB2ZXJ5IHNpZ25pZmljYW50IHByZWRpY3RvciBvZiBwZXJmb3JtYW5jZSBhbmQgaXMgY29ycmVsYXRlZCB3aXRoIHJlZHVjZWQgZ2FybGljIG11c3RhcmQgc2l6ZS4gV2hldGhlciBpdCBpcyBkb2luZyB0aGUgcmVkdWN0aW9uIG9yIGl0IGNhbiBzaW1wbHkgYXBwZWFyIHdoZW4gZ2FybGljIG11c3RhcmQgaXMgYSB3b3JzdCBwZXJmb3JtZXIgaXMgdW5jbGVhci4gVGhlc2UgZXN0aW1hdGVzIHNob3VsZCBiZSB1c2VkIHRvIHZpc3VhbGl6ZSB0aGUgZWZmZWN0IG9mIHRyZWF0bWVudCBvbiBwZXJmb3JtYW5jZS4gCgojVG8gd2hhdCBkZWdyZWUgZG9lcyBmYW1pbHkgaW5mbHVlbmNlIHBlcmZvcm1hbmNlPwoKZml0ZnVsbDwtbG1lcihHTV9Ub3RhbExlYWZfQXJlYX50cmVhdG1lbnQrRmVybisoMXxGYW1pbHkpKygxfGdoX2JlbmNoKSwgZGF0YT1kYXQyKQpmaXRmdWxsMjwtbG1lcihHTV9Ub3RhbExlYWZfQXJlYX50cmVhdG1lbnQrRmVybisoMXxnaF9iZW5jaCksIGRhdGE9ZGF0MikKCmFub3ZhKGZpdGZ1bGwsZml0ZnVsbDIpICNGYW1pbHkgb25seSBwcmVkaWN0cyBwZXJmb3JtYW5jZSB3aGVuIHBhdGhvZ2VucyBhcmUgYWNjb3VudGVkIGZvci4gCmBgYAoKI01vZGVsIERpYWdub3N0aWNzLiAKYGBge3J9Cgojbm8gaGV0ZXJvc2NlZGFzdGljaXR5CnBsb3QoZml0Nik7cGxvdChmaXQ3KQojZmFpcmx5IG5vcm1hbC4gCnFxbm9ybShyZXNpZChmaXQ2KSk7cXFub3JtKHJlc2lkKGZpdDcpKQojVGhlIG1vZGVsIGFwcGVhcnMgdG8gYmUgYSBnb29kIGZpdC4KYGBgCgojSXMgdGhlcmUgYSBjb3N0IHRvIGdsdWNvc2lub2xhdGUgcHJvZHVjdGlvbj8gCmBgYHtyfQpmaXQ2PC1sbWVyKEdNX1RvdGFsTGVhZl9BcmVhfnRyZWF0bWVudCtCbGFja1BhdGhEYW0rV2hpdGVGdW5nTG9naXMrVGhyaXBzRGFtK0dNX0xlYWZfQXJlYStnbHVjX0NvbmMrKDF8RmFtaWx5KSsoMXxnaF9iZW5jaCksIGRhdGE9ZGF0MikKc3VtbWFyeShmaXQ2KSAjTm8sIGluZmFjdCBnbHVjb3Npbm9sYXRlcyBhcmUgcG9zaXRpdmVseSBjb3JyZWxhdGVkIHdpdGggcGVyZm9ybWFuY2UuIAoKI0lzIHRoZSBjb3N0IGRlcGVuZGVudCBvbiB0aGUgdHJlYXRtZW50CmZpdDc8LWxtZXIoR01fVG90YWxMZWFmX0FyZWF+dHJlYXRtZW50KmdsdWNfQ29uYytCbGFja1BhdGhEYW0rV2hpdGVGdW5nTG9naXMrVGhyaXBzRGFtK0dNX0xlYWZfQXJlYSsoMXxGYW1pbHkpKygxfGdoX2JlbmNoKSwgZGF0YT1kYXQyKQpzdW1tYXJ5KGZpdDcpIAphbm92YShmaXQ2LGZpdDcpI1RoZXJlIGlzIGFuIGludGVyYWN0aW9uIGJldHdlZW4gdHJlYXRtZW50LiBIb3dldmVyIGl0IGlzIHBvc3RpdmUgaW4gYWxsIHRyZWF0bWVudHMgYW5kIG1hcGxlIHBlcmZvcm1hbmNlIHdhcyBub3QgYWNjb3VudGVkIGZvciBzbyB0aGlzIG1vZGVsIGlzIG51bGxpZmllZCBhcyBpdCBpcyB1bmluZm9ybWF0aXZlLiAKCgoKZml0NjwtbG1lcihHTV9Ub3RhbExlYWZfQXJlYX50cmVhdG1lbnQrQmxhY2tQYXRoRGFtK1doaXRlRnVuZ0xvZ2lzK1Rocmlwc0RhbStHTV9MZWFmX0FyZWErZmxhdl9Db25jKygxfEZhbWlseSkrKDF8Z2hfYmVuY2gpLCBkYXRhPWRhdDIpCnN1bW1hcnkoZml0NikgI0FzIGFyZSBmbGF2b25vaWRzLiAKCiNJcyB0aGUgY29zdCBkZXBlbmRlbnQgb24gdGhlIHRyZWF0bWVudD8gCmZpdDc8LWxtZXIoR01fVG90YWxMZWFmX0FyZWF+dHJlYXRtZW50KmZsYXZfQ29uYytCbGFja1BhdGhEYW0rV2hpdGVGdW5nTG9naXMrVGhyaXBzRGFtK0dNX0xlYWZfQXJlYSsoMXxGYW1pbHkpKygxfGdoX2JlbmNoKSwgZGF0YT1kYXQyKQpzdW1tYXJ5KGZpdDYpIAoKYW5vdmEoZml0NixmaXQ3KSAjVGhlcmUgaXMgbm90IGEgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gd2l0aCBmbGF2b25vaWRzLiAKCmBgYAoKCgoKCiNWaXN1YWxpemF0aW9uIC0tIFRoZSBjb25kaXRpb25hbCBiZW5lZml0IG9mIGdsdWNvc2lub2xhdGVzIChhbGxlbG9wYXRoeSkKYGBge3J9CgphbG9uZVNsb3BlPC1mdW5jdGlvbih4KXsKICB5PS0zOTY2LjYwKngrIDEzNzUxLjk2CiAgcmV0dXJuKHkpCn0KbWFwbGVTbG9wZTwtZnVuY3Rpb24oeCl7CiAgeT0oLTQyNTQuMis4NDE3Ljk1KSp4KzEzNzUxLjk2IC05MjQzLjcxCiAgcmV0dXJuKHkpCn0KCm11c3RhcmRTbG9wZTwtZnVuY3Rpb24oeCl7CiAgeT0rMTM3NTEuOTYtODM3Ni42NyNOb24gc2lnbmlmaWNhbnQgc2xvcGUKICByZXR1cm4oeSkKfQoKbWluTTwtbWluKGRhdDIkZ2x1Y19Db25jW2RhdDIkdHJlYXRtZW50PT0ibSJdLG5hLnJtID0gVCkKbWF4TTwtbWF4KGRhdDIkZ2x1Y19Db25jW2RhdDIkdHJlYXRtZW50PT0ibSJdLG5hLnJtID0gVCkKCm1pbkE8LW1pbihkYXQyJGdsdWNfQ29uY1tkYXQyJHRyZWF0bWVudD09ImEiXSxuYS5ybSA9IFQpCm1heEE8LW1heChkYXQyJGdsdWNfQ29uY1tkYXQyJHRyZWF0bWVudD09ImEiXSxuYS5ybSA9IFQpCgptaW5HPC1taW4oZGF0MiRnbHVjX0NvbmNbZGF0MiR0cmVhdG1lbnQ9PSJnbSJdLG5hLnJtID0gVCkKbWF4RzwtbWF4KGRhdDIkZ2x1Y19Db25jW2RhdDIkdHJlYXRtZW50PT0iZ20iXSxuYS5ybSA9IFQpCgojdGlmZigiU2VsZWN0aW9uX0ZpZ3VyZXMvR2x1Y19CZW5lZml0LnRpZmYiLCB1bml0cz0iaW4iLCB3aWR0aD0xMCwgaGVpZ2h0PTYsIHJlcz0zMDApCmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRhdDIpKwogIGdlb21fcG9pbnQoYWVzKHk9R01fVG90YWxMZWFmX0FyZWEseD1nbHVjX0NvbmMsY29sb3VyPXRyZWF0bWVudCksc2l6ZT0yKSsKICBnZW9tX3NlZ21lbnQoeD1taW5BLHhlbmQ9bWF4QSx5PWFsb25lU2xvcGUobWluQSkseWVuZD1hbG9uZVNsb3BlKG1heEEpLGNvbG91cj0iIzAwOUU3MyIsc2l6ZT0xLjUpKwogICAgZ2VvbV9zZWdtZW50KHg9bWluTSx4ZW5kPW1heE0seT1tYXBsZVNsb3BlKG1pbk0pLHllbmQ9bWFwbGVTbG9wZShtYXhNKSxjb2xvdXI9IiNFNjlGMDAiLHNpemU9MS41KSsKICBnZW9tX3NlZ21lbnQoeD1taW5HLHhlbmQ9bWF4Ryx5PW11c3RhcmRTbG9wZShtaW5HKSx5ZW5kPW11c3RhcmRTbG9wZShtYXhHKSxjb2xvdXI9IiM1NkI0RTkiLHNpemU9MS41KSt0aGVtZV9zaW1wbGUoKSsKICB5bGFiKGJxdW90ZShib2xkKCJQZXJmb3JtYW5jZVxuKFRvdGFsIExlYWYgQXJlYSAifihtbV4yKX4iKSIpKSkreGxhYihicXVvdGUoYm9sZCgiW1RvdGFsIEdsdWNvc2lub2xhdGVdICIgKG1nL21sKSkpKSsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcz1jKCIjMDA5RTczIiwiIzU2QjRFOSIsIiNFNjlGMDAiKSxsYWJlbHM9YygiQWxvbmUiLCJHYXJsaWMgTXVzdGFyZCIsIk1hcGxlIikpCiNkZXYub2ZmKCkKCm1pbkEKCgpgYGAKCiNWaXN1YWxpemluZyB0aGUgZWZmZWN0IG9mIGZsYXZvbm9pZCBvbiBmaXRuZXNzLgpgYGB7cn0Kc3VtbWFyeShsbWVyKEdNX1RvdGFsTGVhZl9BcmVhfnRyZWF0bWVudCtmbGF2X0NvbmMrQmxhY2tQYXRoRGFtK0Zlcm4rKDF8RmFtaWx5KSsoMXxnaF9iZW5jaC9naF9jb2wpLCBkYXRhPWRhdDIpKQoKYWxvbmVTbG9wZTwtZnVuY3Rpb24oeCl7CiAgeT0yMDI0LjYyICp4KyAgODAzNS4zMAogIHJldHVybih5KQp9Cm1hcGxlU2xvcGU8LWZ1bmN0aW9uKHgpewogIHk9KDIwMjQuNjIgKSp4KyA4MDM1LjMwIC0xMDY3LjAyCiAgcmV0dXJuKHkpCn0KCm11c3RhcmRTbG9wZTwtZnVuY3Rpb24oeCl7CiAgeT0yMDI0LjYyICp4KyA4MDM1LjMwLTM3NDYuOTEjTm9uIHNpZ25pZmljYW50IHNsb3BlCiAgcmV0dXJuKHkpCn0KCm1pbk08LW1pbihkYXQyJGZsYXZfQ29uY1tkYXQyJHRyZWF0bWVudD09Im0iXSxuYS5ybSA9IFQpCm1heE08LW1heChkYXQyJGZsYXZfQ29uY1tkYXQyJHRyZWF0bWVudD09Im0iXSxuYS5ybSA9IFQpCgptaW5BPC1taW4oZGF0MiRmbGF2X0NvbmNbZGF0MiR0cmVhdG1lbnQ9PSJhIl0sbmEucm0gPSBUKQptYXhBPC1tYXgoZGF0MiRmbGF2X0NvbmNbZGF0MiR0cmVhdG1lbnQ9PSJhIl0sbmEucm0gPSBUKQoKbWluRzwtbWluKGRhdDIkZmxhdl9Db25jW2RhdDIkdHJlYXRtZW50PT0iZ20iXSxuYS5ybSA9IFQpCm1heEc8LW1heChkYXQyJGZsYXZfQ29uY1tkYXQyJHRyZWF0bWVudD09ImdtIl0sbmEucm0gPSBUKQoKCiN0aWZmKCJTZWxlY3Rpb25fRmlndXJlcy9GbGF2X0JlbmVmaXQudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTEwLCBoZWlnaHQ9NiwgcmVzPTMwMCkKZ2dwbG90KGRhdDIpKwogIGdlb21fcG9pbnQoYWVzKHk9R01fVG90YWxMZWFmX0FyZWEseD1mbGF2X0NvbmMsY29sb3VyPXRyZWF0bWVudCksc2l6ZT0yKSsKICBnZW9tX3NlZ21lbnQoeD1taW5BLHhlbmQ9bWF4QSx5PWFsb25lU2xvcGUobWluQSkseWVuZD1hbG9uZVNsb3BlKG1heEEpLGNvbG91cj0iIzAwOUU3MyIsc2l6ZT0xLjUpKwogICAgZ2VvbV9zZWdtZW50KHg9bWluTSx4ZW5kPW1heE0seT1tYXBsZVNsb3BlKG1pbk0pLHllbmQ9bWFwbGVTbG9wZShtYXhNKSxjb2xvdXI9IiNFNjlGMDAiLHNpemU9MS41KSt0aGVtZV9zaW1wbGUoKSsKICBnZW9tX3NlZ21lbnQoeD1taW5HLHhlbmQ9bWF4Ryx5PW11c3RhcmRTbG9wZShtaW5HKSx5ZW5kPW11c3RhcmRTbG9wZShtYXhHKSxjb2xvdXI9IiM1NkI0RTkiLHNpemU9MS41KSt0aGVtZV9zaW1wbGUoKSsKICB5bGFiKGJxdW90ZShib2xkKCJQZXJmb3JtYW5jZVxuKFRvdGFsIExlYWYgQXJlYSAifihtbV4yKX4iKSIpKSkreGxhYihicXVvdGUoYm9sZCgiW1RvdGFsIEZsYXZvbm9pZF0gIiAobWcvbWwpKSkpKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzPWMoIiMwMDlFNzMiLCIjNTZCNEU5IiwiI0U2OUYwMCIpLGxhYmVscz1jKCJBbG9uZSIsIkdhcmxpYyBNdXN0YXJkIiwiTWFwbGUiKSkKI2Rldi5vZmYoKQpgYGAKCiNWaXN1YWxpemF0aW9uLS0gVGhlIERldHJpbWVudCBvZiBwYXRob2dlbnMgYW5kIGZlcm5zCmBgYHtyfQpzdW1tYXJ5KGxtZXIoR01fVG90YWxMZWFmX0FyZWEgfiBGZXJuKwooMSB8IEZhbWlseSkgKyAoMSB8IGdoX2JlbmNoL2doX2NvbCkgLGRhdGE9ZGF0MikpCgphPC1nZ3Bsb3QoZGF0MikrCiAgZ2VvbV9wb2ludChhZXMoeT1HTV9Ub3RhbExlYWZfQXJlYSx4PUJsYWNrUGF0aERhbSkpK3RoZW1lX3NpbXBsZV9tdWx0aUNvbCgpKwogIGdlb21fYWJsaW5lKGludGVyY2VwdD04MjgxLjc2LHNsb3BlID0gLTEwNS4yOCxzaXplPTEuNSkrCiAgeGxhYigiQmxhY2sgUGF0aG9nZW4gRGFtYWdlIikKCmI8LWdncGxvdChkYXQyW2RhdDIkV2hpdGVGdW5nRGFtPDMwLF0pKwogIGdlb21fcG9pbnQoYWVzKHk9R01fVG90YWxMZWFmX0FyZWEseD1XaGl0ZUZ1bmdEYW0pLGNvbG91cj0iIzk5OTk5OSIpK3RoZW1lX3NpbXBsZV9tdWx0aUNvbCgpKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjOTk5OTk5Iiwgc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiLG1hcmdpbj1tYXJnaW4oMywwLDMsMCkpLAogICAgICApK3hsYWIoIlBvd2RlcnkgTWlsZGV3IERhbWFnZSIpCgpjPC1nZ3Bsb3QoZGF0MikrCiAgZ2VvbV9wb2ludChhZXMoeT1HTV9Ub3RhbExlYWZfQXJlYSx4PVRocmlwc0RhbSksY29sb3VyPSIjRTY5RjAwIikrdGhlbWVfc2ltcGxlX211bHRpQ29sKCkreGxhYigiVGhyaXBzIERhbWFnZSIpKwogICAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiNFNjlGMDAiLCBzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIsbWFyZ2luPW1hcmdpbigzLDAsMywwKSkpCgpkPC1nZ3Bsb3QoZGF0MikrCiAgZ2VvbV9wb2ludChhZXMoeT1HTV9Ub3RhbExlYWZfQXJlYSx4PUZlcm4pLGNvbG91cj0iIzAwOUU3MyIpK3RoZW1lX3NpbXBsZV9tdWx0aUNvbCgpK3hsYWIoIkZlcm4gQWJ1bmRhbmNlIikrCiAgIGdlb21fYWJsaW5lKGludGVyY2VwdD04MDAzLjQ0LHNsb3BlID0gLTE3OS40NyxzaXplPTEuNSxjb2xvcj0iIzAwOUU3MyIpKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMDA5RTczIiwgc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiLG1hcmdpbj1tYXJnaW4oMywwLDMsMCkpKQogICAKCgpwbG90PC1wbG90X2dyaWQoYSwgYixuY29sPTIscmVsX3dpZHRocyA9IGMoMSwxKSkKCnBsb3QyPC1wbG90X2dyaWQoZCwgYyxuY29sPTIscmVsX3dpZHRocyA9IGMoMSwxKSkKCnBsb3QzPC1wbG90X2dyaWQoYSxiLGMsZCxuY29sPTIscmVsX3dpZHRocyA9IGMoMSwxKSkKCnBsb3Q0PC1wbG90X2dyaWQoYSxiLGMsbmNvbD0xLHJlbF93aWR0aHMgPSBjKDEsMSwxKSkKcGxvdDU8LXBsb3RfZ3JpZChhLGIsYyxuY29sPTMscmVsX3dpZHRocyA9IGMoMSwxLDEpKQoKCnkuZ3JvYjwtdGV4dEdyb2IoYnF1b3RlKGJvbGQoIlNob290IEFyZWEgIihtbV4yKSkpLGdwPWdwYXIoZm9udGZhY2U9ImJvbGQiLGZvbnRzaXplPTIwKSxyb3Q9OTApCgoKI3RpZmYoIlNlbGVjdGlvbl9GaWd1cmVzL1BhdGhvZ2VuRWZmZWN0LnRpZmYiLCB1bml0cz0iaW4iLCB3aWR0aD0xNCwgaGVpZ2h0PTYsIHJlcz0zMDApCmdyaWQuYXJyYW5nZShwbG90LGxlZnQ9eS5ncm9iKQojZGV2Lm9mZigpCgojdGlmZigiU2VsZWN0aW9uX0ZpZ3VyZXMvUGF0aG9nZW5FZmZlY3QyLnRpZmYiLCB1bml0cz0iaW4iLCB3aWR0aD0xNCwgaGVpZ2h0PTYsIHJlcz0zMDApCmdyaWQuYXJyYW5nZShwbG90MixsZWZ0PXkuZ3JvYikKI2Rldi5vZmYoKQoKI3RpZmYoIlNlbGVjdGlvbl9GaWd1cmVzL1BhdGhvZ2VuRWZmZWN0My50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9MTQsIGhlaWdodD0xMCwgcmVzPTMwMCkKZ3JpZC5hcnJhbmdlKHBsb3QzLGxlZnQ9eS5ncm9iKQojZGV2Lm9mZgoKZ3JpZC5hcnJhbmdlKHBsb3Q0LGxlZnQ9eS5ncm9iKQoKCiN0aWZmKCJTZWxlY3Rpb25fRmlndXJlcy9QYXRob2dlbkVmZmVjdDUudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTE2LCBoZWlnaHQ9NSwgcmVzPTMwMCkKZ3JpZC5hcnJhbmdlKHBsb3Q1LGxlZnQ9eS5ncm9iKQojZGV2Lm9mZgoKI3RpZmYoIlNlbGVjdGlvbl9GaWd1cmVzL0Zlcm5FZmZlY3QudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTgsIGhlaWdodD02LCByZXM9MzAwKQpncmlkLmFycmFuZ2UoZCxsZWZ0PXkuZ3JvYikKI2Rldi5vZmYKCmBgYAoKCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KI1BhcnQgMgoKCgoKCiNJbmZsdWVuY2Ugb2YgZ2x1YyBhbmQgZmxhdiBvbiBkZWZlbmNlLiAKYGBge3J9CgpoaXN0KGRhdCRGZXJuKQpoaXN0KGRhdCRUaHJpcHNEYW0pCmhpc3QoZGF0JFdoaXRlRnVuZ0RhbSkKaGlzdChkYXQkQmxhY2tQYXRoRGFtKQoKZGF0JEJsYWNrUGF0aERhbQoKI1RoaXMgZGF0YSBpcyB2ZXJ5IHplcm8gaW5mbGF0ZWQgYW5kIGEgcG9pc3NvbiBtb2RlbCB3aWxsIGJlIHRvbyBvdmVyZGlzcGVyc2VkLiBBIE5lZ2F0aXZlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbiB3aWxsIGJlIHVzZWQuIApgYGAKCgoKI01vZGVsbGluZyA6IE5lZ2F0aXZlIGJpbm9taWFsIG9uIFRocmlwcyBEYW1hZ2UuIApgYGB7cn0KbGlicmFyeSgiZ2xtbVRNQiIpCgpkYXQkVGhyaXBzRGFtPC1jZWlsaW5nKGRhdCRUaHJpcHNEYW0pCgpmaXRfZnVsbDwtZ2xtbVRNQihUaHJpcHNEYW1+dHJlYXRtZW50K2dsdWNfQ29uYytmbGF2X0NvbmMrKDF8RmFtaWx5L1RhZykrKDF8Z2hfYmVuY2gpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0KQoKZml0XzE8LXVwZGF0ZShmaXRfZnVsbCx+Li10cmVhdG1lbnQpCmFub3ZhKGZpdF9mdWxsLGZpdF8xKSAjdHJlYXRtZW50IGlzIHVuaW1wb3J0YW50LiAKCmZpdF8yPC11cGRhdGUoZml0XzEsfi4rIGdsdWNfQ29uYzpmbGF2X0NvbmMpCgphbm92YShmaXRfMSxmaXRfMikjaW50ZXJhY3Rpb24gdW5pbXBvcnRhbnQuIAoKCmZpdF8xPC1nbG1tVE1CKFRocmlwc0RhbX5nbHVjX0NvbmMrZmxhdl9Db25jKygxfEZhbWlseS9UYWcpKygxfGdoX2JlbmNoKSxmYW1pbHk9bmJpbm9tMixkYXRhPWRhdFshaXMubmEoZGF0JGZsYXZfQ29uYyksXSkKCmZpdF8yPC11cGRhdGUoZml0XzEsfi4tIGZsYXZfQ29uYykKYW5vdmEoZml0XzEsZml0XzIpIwojRmxhdl9Db25jIGlzIGhpZ2hseSBpbXBvcnRhbnQuIAoKCgpmaXRfMjwtdXBkYXRlKGZpdF8xLH4uLSBnbHVjX0NvbmMpCmFub3ZhKGZpdF8xLGZpdF8yKSMgZ2x1YyBjb25jIGRvZXMgbm90IGFwcGVhciB0byBiZSBzaWduaWZpY2FudC4gSSB3aWxsIHRyeSB1c2luZyB0aGUgd2hvbGUgZ2x1YyBjb25jIGRhdGEgc2V0LiAKCmZpdF8xPC1nbG1tVE1CKFRocmlwc0RhbX5nbHVjX0NvbmMrKDF8RmFtaWx5L1RhZykrKDF8Z2hfYmVuY2gpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0WyFpcy5uYShkYXQkZ2x1Y19Db25jKSxdKQoKZml0XzI8LXVwZGF0ZShmaXRfMSx+Li0gZ2x1Y19Db25jKQphbm92YShmaXRfMSxmaXRfMikjIGdsdWMgY29uYyBpcyBoaWdobHkgc2lnbmlmaWNhbnQgaG93ZXZlciB3aGVuIGZsYXZvbm9pZHMgYXJlIGV4Y2x1ZGVkLiBUaGVyZWZvcmUgc2Vjb25kYXJ5IGNvbXBvdW5kcywgYm90aCBnbHVjb3Npbm9sYXRlcyBhbmQgZmxhdm9ub2lkcyBwcmVkaWN0cyByZWR1Y3Rpb24gaW4gdGhyaXBzIGRhbWFnZS4gCgojQmVzdCBtb2RlbCBpbmNsdWRlcyBib3RoLCBob3dldmVyLCBwdXR0aW5nIGJvdGggaW4gdGhlIHNhbWUgbW9kZWwgd2lsbCBkaXN0cmlidXRlIHRoZSBlZmZlY3QgYW1vdW5nc3QgYm90aCBvZiB0aGUgdGVybXMuIFRoaXMgbWlnaHQgbm90IGJlIGFwcHJvcHJpYXRlLCBidXQgaSB3aWxsIGNoZWNrIGZvciB0aGlzLiAKCmZpdF9nPC1nbG1tVE1CKFRocmlwc0RhbX5nbHVjX0NvbmMrKDF8RmFtaWx5L1RhZykrKDF8Z2hfYmVuY2gpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0WyFpcy5uYShkYXQkZ2x1Y19Db25jKSxdKQpmaXRfZjwtZ2xtbVRNQihUaHJpcHNEYW1+Zmxhdl9Db25jKygxfEZhbWlseS9UYWcpKygxfGdoX2JlbmNoKSxmYW1pbHk9bmJpbm9tMixkYXRhPWRhdFshaXMubmEoZGF0JGZsYXZfQ29uYyksXSkKZml0X2Z1bGw8LWdsbW1UTUIoVGhyaXBzRGFtfmdsdWNfQ29uYytmbGF2X0NvbmMrKDF8RmFtaWx5L1RhZykrKDF8Z2hfYmVuY2gpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0KQoKc3VtbWFyeShmaXRfZikkY29lZgpzdW1tYXJ5KGZpdF9nKSRjb2VmCnN1bW1hcnkoZml0X2Z1bGwpJGNvZWYKCiNBcyBleHBlY3RlZCwgdGhlIGNvZWZmaWNpZW50cyBhcmUgZGlzdHJpYnV0ZWQgZXZlbmx5IGFtb3VuZ3N0IGdsdWMgYW5kIGZsYXYgY29uY2VudHJhdGlvbnMsIHRoZSBjb25jbHVzaW9uIGlzIHRoYXQgYm90aCByZWR1Y2UgdGhyaXBzIGFidW5kYW5jZSBhbmQgaXQgaXMgbm90IHBvc3NpYmxlIHRvIHRlbGwgd2hpY2ggZG9lcyB0aGUgbW9zdCwgaG93ZXZlciwgdGhlIGVmZmVjdCBpcyBtb3JlIHNpZ25pZmljYW50IGZvciBmbGF2b25vaWRzLiAKCnBsb3QocmVzaWQoZml0X2YpKQpwbG90KHJlc2lkKGZpdF9mKV4yKQojVGhlIG1vZGVsIGFwcGVhcnMgdG8gYmUgYSB2ZXJ5IGdvb2QgZml0LiAKCgojUGVybXV0YXRpb24gdGVzdC4uLi4KZml0X2Y8LWdsbW1UTUIoVGhyaXBzRGFtfmZsYXZfQ29uYysoMXxGYW1pbHkvVGFnKSsoMXxnaF9iZW5jaCksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXQpCnN1bW1hcnkoZml0X2YpCgpkYXRQZXJUZXN0PC1kYXQKelN0b3JlPC1jKCkKZm9yKGkgaW4gMTo1MDApewogICNSYW5kb21pemUgZmxhdm9ub2lkIGNvbmNlbnRyYXRpb24uCiAgZGF0UGVyVGVzdCRmbGF2X0NvbmM8LXNhbXBsZShkYXQkZmxhdl9Db25jLGxlbmd0aChkYXQkZmxhdl9Db25jKSxyZXBsYWNlID0gRikKICAKICAjUnVuIE1vZGVsIHdpdGggcmFuZG9taXplZCBmbGF2b25vaWQgY29uY2VudHJhdGlvbiBhbmQgZXh0cmFjdCB0ZXN0IHN0YXRpc3RpYwogIGZsYXZadmFsPC1zdW1tYXJ5KHVwZGF0ZShmaXRfZixkYXRhPWRhdFBlclRlc3QpKSRjb2VmW1sxXV1bMiwzXQogIAogICNTdG9yZSB6IHZhbHVlLgogIHpTdG9yZVtpXTwtZmxhdlp2YWwKfQoKc3VtKHpTdG9yZTw9LTUuMzU2KS9sZW5ndGgoelN0b3JlKQojV3RoIHRoZSBwZXJtdXRhdGlvbiB0ZXN0LCB0aGUgcCB2YWx1ZSBpcyBzdGlsbCAwLCB3aGljaCBpbmRpY2F0ZXMgdGhhdCB0aGlzIG1vZGVsIGlzIGEgdmVyeSBnb29kIGZpdCBmb3IgdGhlIGRhdGEuIApoaXN0KHpTdG9yZSkKCmBgYAoKCiNWaXN1YWxpemU6IFRocmlwcyBEYW1hZ2UgcHJlZGljdGVkIGJ5IGdsdWNvc2lub2xhdGVzIGFuZCBmbGF2b25vaWRzCgpgYGB7cn0KCnNvdXJjZSgiR0dQbG90X1RoZW1lcy5SIikKI1JldmVyc2luZyBsaW5rIGZ1bmN0aW9uLCB0byBlc3RpbWF0ZSB0aGUgZGF0YSBvbiB0aGUgcmVzcG9uc2Ugc2NhbGUuIApmbGF2U2xvcGU9ZnVuY3Rpb24oeCl7CiAgeT1leHAoLTIuNDYyMSAqeCsyLjk3NDYpCiAgcmV0dXJuKHkpCn0KZ2x1Y1Nsb3BlPWZ1bmN0aW9uKHgpewogIHk9ZXhwKC0yLjc4NjkqeCszLjU3NTUpCiAgcmV0dXJuKHkpCn0KCiNEZXRlcm1pbmluZyB4IHJhbmdlIHRvIGZpdCB0aGUgbGluZSB0byAKZmxhdnBsb3Q9c2VxKG1pbihkYXQkZmxhdl9Db25jLG5hLnJtID0gVCksbWF4KGRhdCRmbGF2X0NvbmMsbmEucm09VCksbGVuZ3RoLm91dCA9IDY4OCkKZ2x1Y3Bsb3Q9c2VxKG1pbihkYXQkZ2x1Y19Db25jLG5hLnJtID0gVCksbWF4KGRhdCRnbHVjX0NvbmMsbmEucm09VCksbGVuZ3RoLm91dCA9IDcwOCkKCiNDYWxjdWxhdGluZyBzbG9wZSB2YWx1ZXMKZmxhdnk8LWZsYXZTbG9wZShmbGF2cGxvdCkKZ2x1Y3k8LWdsdWNTbG9wZShnbHVjcGxvdCkKCgojdGlmZigiRGVmZW5jZV9GaWd1cmVzL0ZsYXZvbm9pZFRocmlwcy50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9MTAsIGhlaWdodD02LCByZXM9MzAwKQpnZ3Bsb3QoZGF0WyFpcy5uYShkYXQkZmxhdl9Db25jKSxdKSsKICBnZW9tX3BvaW50KGFlcyh5PVRocmlwc0RhbSx4PWZsYXZfQ29uYykpK3RoZW1lX3NpbXBsZSgpKwogIGdlb21fcGF0aCh4PWZsYXZwbG90LHk9Zmxhdnksc2l6ZT0xLGNvbG91cj0iIzk5OTk5OSIpKwogIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsNzAsNSkpKwogIHlsYWIoIlRocmlwcyBEYW1hZ2UiKSsKeGxhYihicXVvdGUoYm9sZCgiW1RvdGFsIEZsYXZvbm9pZF0gIiAobWcvbWwpKSkpCiNkZXYub2ZmKCkKCmdncGxvdChkYXRbIWlzLm5hKGRhdCRnbHVjX0NvbmMpLF0pKwogIGdlb21fcG9pbnQoYWVzKHk9VGhyaXBzRGFtLHg9Z2x1Y19Db25jKSkrdGhlbWVfc2ltcGxlKCkrCiAgZ2VvbV9wYXRoKHg9Z2x1Y3Bsb3QseT1nbHVjeSxzaXplPTEsY29sb3VyPSIjOTk5OTk5IikrCiAgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCw3MCw1KSkrCiAgeWxhYigiVGhyaXBzIERhbWFnZSIpKwp4bGFiKGJxdW90ZShib2xkKCJbVG90YWwgR2x1Y29zaW5vbGF0ZV0gIiAobWcvbWwpKSkpCgpgYGAKCgoKCgoKSSB0aGluayB0aGF0IGEgbG9naXN0aWMgcmVncmVzc2lvbiBpcyBtb3JlIGFwcHJvcHJpYXRlIGZvciBmdW5nYWwgYWJ1bmRhbmNlLCBiZWNhdXNlIHRoZSBjb3VudCBvZiBmdW5nYWwgaW5mZWN0aW9uIGNvdWxkIGJlIGFyYnVpdHJhcnksIGVzcGVjaWFsbHkgd2hlbiBmdW5nYWwgcGF0Y2hlcyB3ZXJlIGxhcmdlIG9yIHRoZSBsZWFmIHdhcyBjb21wbGV0ZWx5IGNvdmVyZWQuIAoKI1doaXRlUGF0aERhbSAtLSBsb2dpc3RpYyByZWdyZXNzaW9uIApgYGB7cn0KCiNUaGlzIGlzIHRoZSBiaWdnZXN0IG1vZGVsIHRoYXQgY291bGQgY29udmVyZ2UuIC4uLiBpbnRlcmFjdGlvbiB3aXRoIGZsYXZvbm9pZCBjb3VsZCBub3QuCmZpdF9mdWxsX2c8LWdsbWVyKFdoaXRlRnVuZ0xvZ2lzfnRyZWF0bWVudCpnbHVjX0NvbmMrZmxhdl9Db25jKygxfEZhbWlseSksZmFtaWx5PWJpbm9taWFsLGRhdGE9ZGF0MlshaXMubmEoZGF0MiRmbGF2X0NvbmMpLF0pCgpmaXQuMTwtdXBkYXRlKGZpdF9mdWxsX2csfi4tZmxhdl9Db25jKQphbm92YShmaXRfZnVsbF9nLGZpdC4xKSAjRmxhdm9ub2lkIENvbmNlbnRyYXRpb24gaXMgbm90IHNpZ25pZmljYW50LiAKCgojVGVzdGluZyBnbHVjb3Npbm9sYXRlIHRyZWF0bWVudCBpbnRlcmFjdGlvbi4gCmZpdC4yPC1nbG1lcihXaGl0ZUZ1bmdMb2dpc350cmVhdG1lbnQqZ2x1Y19Db25jKygxfEZhbWlseSksZmFtaWx5PWJpbm9taWFsLGRhdGE9ZGF0MikKZml0LjM8LWdsbWVyKFdoaXRlRnVuZ0xvZ2lzfnRyZWF0bWVudCtnbHVjX0NvbmMrKDF8RmFtaWx5KSxmYW1pbHk9Ymlub21pYWwsZGF0YT1kYXQyKQphbm92YShmaXQuMixmaXQuMykgI0dsdWNvc2lub2xhdGU6VHJlYXRtZW50IGludGVyYWN0aW9uIGlzIG5vdCBzaWduaWZpY2FudC4KCiNUZXN0aW5nIGdsdWNvc2lub2xhdGUgaW52b2x2bWVudCBhdCBhbGwuCmZpdC40PC1nbG1lcihXaGl0ZUZ1bmdMb2dpc350cmVhdG1lbnQrKDF8RmFtaWx5KSxmYW1pbHk9Ymlub21pYWwsZGF0YT1kYXQyWyFpcy5uYShkYXQyJGdsdWNfQ29uYyksXSkKZml0LjM8LWdsbWVyKFdoaXRlRnVuZ0xvZ2lzfnRyZWF0bWVudCtnbHVjX0NvbmMrKDF8RmFtaWx5KSxmYW1pbHk9Ymlub21pYWwsZGF0YT1kYXQyWyFpcy5uYShkYXQyJGdsdWNfQ29uYyksXSkKYW5vdmEoZml0LjQsZml0LjMpICNHbHVjb3Npbm9sYXRlIENvbmNlbnRyYXRpb24gaXMgbm90IGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yCgojVGVzdGluZyBlZmZlY3Qgb2YgdHJlYXRtZW50CmZpdC40PC1nbG1lcihXaGl0ZUZ1bmdMb2dpc350cmVhdG1lbnQrKDF8RmFtaWx5KSxmYW1pbHk9Ymlub21pYWwsZGF0YT1kYXQyKQpmaXQuNTwtZ2xtZXIoV2hpdGVGdW5nTG9naXN+MSsoMXxGYW1pbHkpLGZhbWlseT1iaW5vbWlhbCxkYXRhPWRhdDIpCmFub3ZhKGZpdC40LGZpdC41KQojdHJlYXRtZW50IGlzIHNpZ25pZmljYW50Li4uLi4uCgpzdW1tYXJ5KGZpdC40KSAjR2FybGljIG11c3RhcmQgaW4gdGhlIG1hcGxlIHRyZWF0bWVudCBoYXZlIGxlc3Mgb2NjdXJlbmNlIG9mIGZ1bmdhbCBjb2xvbml6YXRpb24uIAoKcGxvdChmaXQuNCkKCiNQZXJtdXRhdGlvbiB0ZXN0CmRhdFBlclRlc3Q8LWRhdDIKdHJlYXR6U3RvcmU8LWMoKQpmb3IoaSBpbiAxOjIwMDApewogICNSYW5kb21pemUgZmxhdm9ub2lkIGNvbmNlbnRyYXRpb24uCiAgZGF0UGVyVGVzdCR0cmVhdG1lbnQ8LXNhbXBsZShkYXQyJHRyZWF0bWVudCxsZW5ndGgoZGF0MiR0cmVhdG1lbnQpLHJlcGxhY2UgPSBGKQogICNSdW4gTW9kZWwgd2l0aCByYW5kb21pemVkIGZsYXZvbm9pZCBjb25jZW50cmF0aW9uIGFuZCBleHRyYWN0IHRlc3Qgc3RhdGlzdGljCiAgdHJlYXRadmFsPC1zdW1tYXJ5KHVwZGF0ZShmaXQuNCxkYXRhPWRhdFBlclRlc3QpKSRjb2VmWzMsM10KICAKICAjU3RvcmUgeiB2YWx1ZS4KICB0cmVhdHpTdG9yZVtpXTwtdHJlYXRadmFsCn0Kc3VtKHRyZWF0elN0b3JlPD0tMi45MTYpL2xlbmd0aCh0cmVhdHpTdG9yZSkKI1NpbXVsYXRlZCBwIHZhbHVlIGlzIGFib3V0IDAuMDAyNSwgd2hpY2ggaXMgdmVyeSBzaW1pbGFyIHRvIHRoZSAwLjAwMyBJIG9ic2VydmVkLCBzdWdnZXN0aW5nIHRoaXMgaXMgYSBnb29kIG1vZGVsLiAKYGBgCgoKCiNWaXN1YWxpemluZyAtLSBlZmZlY3Qgb2YgdHJlYXRtZW50IG9uIHByb3BvcnRpb24gb2YgZnVuZ2FsIGFidW5kYW5jZS4gCmBgYHtyfQojU3VtbWFyaXppbmcgZm9yIERpc3BsYXk6IGdlbmVyYXRpbmcgZnJlcXVlbmN5IG9mIHdoaXRlIGZ1bmFsIGluZmVjdGlvbiBieSB0cmVhdG1lbnQKcGxvdDwtZGF0MiAlPiUgZHJvcF9uYShXaGl0ZUZ1bmdMb2dpcykgJT4lIGdyb3VwX2J5KHRyZWF0bWVudCkgJT4lIHN1bW1hcml6ZShQZXJjV2hpdEZ1bmc9c3VtKFdoaXRlRnVuZ0xvZ2lzKS9sZW5ndGgoV2hpdGVGdW5nTG9naXMpKjEwMCkKCgojdGlmZigiRGVmZW5jZV9GaWd1cmVzL1RyZWF0TWVhbldoaXRlRnVuZy50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9OCwgaGVpZ2h0PTUsIHJlcz0zMDApCmdncGxvdChwbG90KSsKICBnZW9tX2NvbChhZXMoeD10cmVhdG1lbnQseT1QZXJjV2hpdEZ1bmcsZmlsbD10cmVhdG1lbnQpKSt0aGVtZV9zaW1wbGUoKSt5bGFiKCJGdW5nYWwgQWJ1bmRhbmNlXG4gKCUgSW5mZWN0ZWQpIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDMwLDUpKSsKc2NhbGVfeF9kaXNjcmV0ZShuYW1lPSIiLGxhYmVscz1jKCJBbG9uZSIsIkdhcmxpYyBNdXN0YXJkIiwiTWFwbGUiKSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDlFNzMiLCIjNTZCNEU5IiwiI0U2OUYwMCIpLGxhYmVscz1jKCJBbG9uZSIsIkdhcmxpYyBNdXN0YXJkIiwiTWFwbGUiKSkrCiAgdGhlbWVfc2ltcGxlX211bHRpQ29sKCkrdGhlbWUoYXhpcy50aXRsZS55ID0gIGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIixtYXJnaW49bWFyZ2luKDMsMjAsMywwKSkpCiNkZXYub2ZmKCkKCmBgYAoKCgojTW9kZWxsaW5nOiBOZWdhdGl2ZSBCaW5vbWlhbCAtLSBCbGFja1BhdGhEYW0gCmBgYHtyfQpkYXQkQmxhY2tQYXRoRGFtPC1jZWlsaW5nKGRhdCRCbGFja1BhdGhEYW0pCmZpdF9mdWxsPC1nbG1tVE1CKEJsYWNrUGF0aERhbX50cmVhdG1lbnQrZ2x1Y19Db25jK2ZsYXZfQ29uYysoMXxGYW1pbHkvVGFnKSsoMXxnaF9iZW5jaCksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXQpCmZpdF9mdWxsXzAuMTwtZ2xtbVRNQihCbGFja1BhdGhEYW1+dHJlYXRtZW50K2dsdWNfQ29uYytmbGF2X0NvbmMrKDF8RmFtaWx5L1RhZyksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXQpCgphbm92YShmaXRfZnVsbCxmaXRfZnVsbF8wLjEpI2doX0JlbmNoIHdhcyBub3QgYW4gaW1wb3J0YW50IHJhbmRvbSBlZmZlY3QgaW4gdGhpcyBtb2RlbC4gCgpmaXRfZnVsbF8wLjE8LWdsbW1UTUIoQmxhY2tQYXRoRGFtfnRyZWF0bWVudCtnbHVjX0NvbmMrZmxhdl9Db25jKygxfEZhbWlseS9UYWcpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0WyFpcy5uYShkYXQkZmxhdl9Db25jKSxdKQpmaXRfMTwtZ2xtbVRNQihCbGFja1BhdGhEYW1+dHJlYXRtZW50K2dsdWNfQ29uYysoMXxGYW1pbHkvVGFnKSxmYW1pbHk9bmJpbm9tMixkYXRhPWRhdFshaXMubmEoZGF0JGZsYXZfQ29uYyksXSkKYW5vdmEoZml0X2Z1bGxfMC4xLGZpdF8xKSAjRmxhdiBjb25jIGlzIGEgdmVyeSBpbXBvcnRhbnQgcHJlZGljdG9yIG9mIGJsYWNrIHBhdGhvZ2VuIGRhbWFnZS4gCgpmaXRfMTwtZ2xtbVRNQihCbGFja1BhdGhEYW1+dHJlYXRtZW50K2dsdWNfQ29uYysoMXxGYW1pbHkvVGFnKSxmYW1pbHk9bmJpbm9tMixkYXRhPWRhdFshaXMubmEoZGF0JGdsdWNfQ29uYyksXSkKZml0XzI8LWdsbW1UTUIoQmxhY2tQYXRoRGFtfnRyZWF0bWVudCsoMXxGYW1pbHkvVGFnKSxmYW1pbHk9bmJpbm9tMixkYXRhPWRhdFshaXMubmEoZGF0JGdsdWNfQ29uYyksXSkKYW5vdmEoZml0XzEsZml0XzIpICNHbHVjb3Npbm9sYXRlcyBhcmUgbm90IGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yIGF0IGFsbC4gCgoKZml0XzI8LWdsbW1UTUIoQmxhY2tQYXRoRGFtfnRyZWF0bWVudCtmbGF2X0NvbmMrKDF8RmFtaWx5L1RhZyksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXQpCmZpdF8zPC1nbG1tVE1CKEJsYWNrUGF0aERhbX5mbGF2X0NvbmMrKDF8RmFtaWx5L1RhZyksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXQpCmFub3ZhKGZpdF8zLGZpdF8yKSAjVHJlYXRtZW50IGlzIGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yIG9mIGJsYWNrIHBhdGhvZ2VuIGRhbWFnZS4gCgoKI1RoZXJlZm9yZSwgdGhlIGJlc3QgbW9kZWwgaXMgb25lIHdpdGggZmxhdm9ub2lkcyBhbmQgdHJlYXRtZW50LiAKCnN1bW1hcnkoZml0XzIpCgpwbG90KHJlc2lkKGZpdF8yKSkgI01vZGVsIGZpdHMgd2VsbC4KCiNQZXJtdXRhdGlvbiB0ZXN0LiAKCmRhdFBlclRlc3Q8LWRhdAp6U3RvcmVmbGF2PC1jKCkKelN0b3JldHJlYXQ8LWMoKQpmb3IoaSBpbiAxOjUwMCl7CiAgI1JhbmRvbWl6ZSBmbGF2b25vaWQgY29uY2VudHJhdGlvbi4KICBkYXRQZXJUZXN0JGZsYXZfQ29uYzwtc2FtcGxlKGRhdCRmbGF2X0NvbmMsbGVuZ3RoKGRhdCRmbGF2X0NvbmMpLHJlcGxhY2UgPSBGKQogIGRhdFBlclRlc3QkdHJlYXRtZW50PC1zYW1wbGUoZGF0JHRyZWF0bWVudCxsZW5ndGgoZGF0JHRyZWF0bWVudCkscmVwbGFjZSA9IEYpCgogICNOZXcgTW9kZWwgd2l0aCByYW5kb21pemVkIHRyZWF0bWVudCBhbmQgZmxhdm9ub2lkcwogIG5ld01vZDwtdXBkYXRlKGZpdF8yLGRhdGE9ZGF0UGVyVGVzdCkKICAKICAjIEV4dHJhY3QgdGVzdCBzdGF0aXN0aWMKICBmbGF2WnZhbDwtc3VtbWFyeShuZXdNb2QpJGNvZWZbWzFdXVs0LDNdCiAgdHJlYXRadmFsPC1zdW1tYXJ5KG5ld01vZCkkY29lZltbMV1dWzMsM10KCiAgI1N0b3JlIHogdmFsdWUuCiAgelN0b3JlZmxhdltpXTwtZmxhdlp2YWwKICB6U3RvcmV0cmVhdFtpXTwtdHJlYXRadmFsCn0KCiN0cmVhdG1lbnQgcCB2YWx1ZSAKc3VtKHpTdG9yZXRyZWF0PD0tMi4wODIpL2xlbmd0aCh6U3RvcmV0cmVhdCkgCiNUaGUgcCB2YWx1ZSBmb3IgdHJlYXRtZW50IGlzIDAuMDIyLCB3aGljaCBpcyB2ZXJ5IGNsb3NlIHRvIHRoZSBvYnNlcnZlZCAwLjAzIHAgdmFsdWUuCnN1bSh6U3RvcmVmbGF2PD0tMi44ODYzKS9sZW5ndGgoelN0b3JlZmxhdikKI1RoZSBwIHZhbHVlIG9mIGZsYXZvbm9pZHMgaXMgMC4wMDIsIHdoaWNoIGlzIHZlcnkgY2xvc2UgdG8gdGhlIG9ic2VydmVkIDAuMDAzIHAgdmFsdWUuCiNDb25jbHVzaW9uOiBUaGlzIGlzIGEgZ29vZCBtb2RlbC4gCmBgYAoKCiNWaXN1YWxpemluZzogVGhlIGVmZmVjdCBvZiB0cmVhdG1lbnQgYW5kIGZsYXZvbm9pZCBhYnVuZGFuY2Ugb24gYmxhY2sgcGF0aG9nZW4gYWJ1bmRhbmNlLiAKYGBge3J9CnNvdXJjZSgiR0dQbG90X1RoZW1lcy5SIikKI1JldmVyc2luZyBsaW5rIGZ1bmN0aW9uLCB0byBlc3RpbWF0ZSB0aGUgZGF0YSBvbiB0aGUgcmVzcG9uc2Ugc2NhbGUuIApmbGF2U2xvcGU9ZnVuY3Rpb24oeCxpbnQpewogIHk9ZXhwKC0xLjUwNjAqeCtpbnQpCiAgcmV0dXJuKHkpCn0KCgoKI0RldGVybWluaW5nIHggcmFuZ2UgdG8gZml0IHRoZSBsaW5lIHRvIApmbGF2cGxvdD1zZXEobWluKGRhdCRmbGF2X0NvbmMsbmEucm0gPSBUKSxtYXgoZGF0JGZsYXZfQ29uYyxuYS5ybT1UKSxsZW5ndGgub3V0ID0gNjgwKQoKCiNDYWxjdWxhdGluZyBzbG9wZSB2YWx1ZXMKZmxhdnlBPC1mbGF2U2xvcGUoZmxhdnBsb3QsIDAuNzgyNikKZmxhdnlHTTwtZmxhdlNsb3BlKGZsYXZwbG90LCAwLjc4MjYrMC4xMDQ5KQpmbGF2eU08LWZsYXZTbG9wZShmbGF2cGxvdCwgMC43ODI2LTAuNTIwNCApCgoKI3RpZmYoIkRlZmVuY2VfRmlndXJlcy9GbGF2b25vaWRUaHJpcHMudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTEwLCBoZWlnaHQ9NiwgcmVzPTMwMCkKZ2dwbG90KGRhdFshaXMubmEoZGF0JGZsYXZfQ29uYyksXSkrCiAgZ2VvbV9wb2ludChhZXMoeT1CbGFja1BhdGhEYW0seD1mbGF2X0NvbmMsY29sb3VyPXRyZWF0bWVudCkpKwp0aGVtZV9zaW1wbGUoKSsKICBnZW9tX3BhdGgoeD1mbGF2cGxvdCx5PWZsYXZ5QSxzaXplPTEsY29sb3VyPSIjMDA5RTczIikrCiAgICBnZW9tX3BhdGgoeD1mbGF2cGxvdCx5PWZsYXZ5R00sc2l6ZT0xLGNvbG91cj0iIzU2QjRFOSIpKwogIGdlb21fcGF0aCh4PWZsYXZwbG90LHk9ZmxhdnlNLHNpemU9MSxjb2xvdXI9IiNFNjlGMDAiKSsKCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXM9YygiIzAwOUU3MyIsIiM1NkI0RTkiLCIjRTY5RjAwIiksbGFiZWxzPWMoIkFsb25lIiwiR2FybGljIE11c3RhcmQiLCJNYXBsZSIpKSsKCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCw3MCw1KSkrCiAgeWxhYigiQmxhY2sgUGF0aG9nZW4gRGFtYWdlIikrCnhsYWIoYnF1b3RlKGJvbGQoIltUb3RhbCBGbGF2b25vaWRdICIgKG1nL21sKSkpKQpgYGAKCgojVmlzdWFsaXphdGlvbiAtLSBCbGFjayBwYXRob2dlbiBkYW1hZ2UgYnkgdHJlYXRtZW50CmBgYHtyfQoKcGxvdDI8LWRhdDIgJT4lIGRyb3BfbmEoQmxhY2tQYXRoRGFtKSAlPiUgZ3JvdXBfYnkodHJlYXRtZW50KSAlPiUgc3VtbWFyaXplKEJsYWNrUGF0aEF2ZT1tZWFuKEJsYWNrUGF0aERhbSxuYS5ybT1UKSkKCmdncGxvdChwbG90MikrCiAgZ2VvbV9jb2woYWVzKHg9dHJlYXRtZW50LHk9QmxhY2tQYXRoQXZlLGZpbGw9dHJlYXRtZW50KSkrdGhlbWVfc2ltcGxlKCkreWxhYigiQmxhY2sgUGF0aG9nZW4gSW5mZWN0aW9uXG4oc3BvdHMvbGVhZikiKSt4bGFiKCJUcmVhdG1lbnQiKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpgYGAKCgoKCiNNb2RlbGxpbmc6IE5lZ2F0aXZlIEJpbm9taWFsLSBGZXJuIGFidW5kYW5jZQpgYGB7cn0KI0JlY2F1c2UgdGhlcmUgYXJlIHR3byBnYXJsaWMgbXVzdGFyZCBpbmRpdmlkdWFscyBwZXIgcG90LCBhbmQgdGhlIHVuaXQgd2UgYXJlIGxvb2tpbmcgYXQgaXMgb25seSByZXBsaWNhYmxlIGF0IHRoZSBwb3QgbGV2ZWwgKGZlcm4gYWJ1bmRhbmNlIGluIGEgcG90KSBkdXBsaWNhdGVzIHdpdGhpbiB0aGUgc2FtZSBwb3QgaW4gdGhlIGdhcmxpYyBtdXN0YXJkIHRyZWF0bWVudCBuZWVkIHRvIGJlIHJlbW92ZWQgYW5kIGF2ZXJhZ2VkIHRvIHJlbW92ZSBwc2V1ZG9yZXBsaWNhdGlvbi4gCgojV2hhdCBpIHdpbGwgZG8gaXMgbWFrZSB0aGUgY29tcGV0aXRpb24gbnVtYmVyIHRoZSB0YWcgZm9yIHRob3NlIGluIHRoZSBHTSB0cmVhdG1lbnQuIFRoaXMgd2lsbCBoYXZlIHRoZSBlZmZlY3Qgb2YgbWFpbnRhaW5pbmcgdGhlIGxlYWYgdmFyaWF0aW9uLCBidXQgYXZlcmFnaW5nIGl0IG92ZXIgZWFjaCBwb3QuIAoKIyBJIHdpbGwgbmVlZCB0byB1c2UgZGF0Miwgc3VtbWFyaXplZCBhdCB0aGUgaW5kaXZpZHVhbCBsZXZlbCwgYmVjYXVzZSB3ZSBoYXZlIGEgc2luZ2xlIG9ic2VydmF0aW9uIGF0IHRoZSBwb3QgbGV2ZWwsIG5vdCBhdCB0aGUgbGVhZiBsZXZlbC4gCmRhdEZlcm48LWRhdDIKZGF0RmVybiRUYWc8LWFzLmNoYXJhY3RlcihkYXRGZXJuJFRhZykKZm9yKGkgaW4gMTpsZW5ndGgoZGF0RmVybiRUYWcpKXsKICBpZighaXMubmEoZGF0RmVybiRjb21wX251bWJlcltpXSkpewogICAgZGF0RmVybiRUYWdbaV08LWRhdEZlcm4kY29tcF9udW1iZXJbaV0KICB9Cn0KZGF0RmVybgojSSBhbSBleGNsdWRpbmcgZmxhdm9ub2lkIGNvbmNlbnRyYXRpb24gYmVjYXVzZSB0aGVyZSB3ZXJlIG5vIGRldGVjdGFibGUgZmxhdm9ub2lkcyBpbiB0aGUgcm9vdCBzYW1wbGVzLiAKZml0X2Z1bGw8LWdsbW1UTUIoRmVybn50cmVhdG1lbnQrZ2x1Y19Db25jKygxfEZhbWlseSkrKDF8Z2hfYmVuY2gpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0RmVybikKZml0X2Z1bGxfMC4xPC1nbG1tVE1CKEZlcm5+dHJlYXRtZW50K2dsdWNfQ29uYysoMXxGYW1pbHkpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0RmVybikKZml0X2Z1bGxfMC4yPC1nbG1tVE1CKEZlcm5+dHJlYXRtZW50K2dsdWNfQ29uYysoMXxnaF9iZW5jaCksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXRGZXJuKQoKYW5vdmEoZml0X2Z1bGwsZml0X2Z1bGxfMC4xKSNCZW5jaCBpcyBhbiBleHRyZW1lbmx5IGltcG9ydGFudCBwcmVkaWN0b3IuIAphbm92YShmaXRfZnVsbCxmaXRfZnVsbF8wLjIpI0ZhbWlseSBpcyBub3QuIAoKCmZpdF9mdWxsPC1nbG1tVE1CKEZlcm5+dHJlYXRtZW50K2dsdWNfQ29uYysoMXxnaF9iZW5jaCksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXRGZXJuWyFpcy5uYShkYXRGZXJuJGdsdWNfQ29uYyksXSkKZml0XzE8LWdsbW1UTUIoRmVybn50cmVhdG1lbnQrKDF8Z2hfYmVuY2gpLGZhbWlseT1uYmlub20yLGRhdGE9ZGF0RmVyblshaXMubmEoZGF0RmVybiRnbHVjX0NvbmMpLF0pCmFub3ZhKGZpdF9mdWxsLGZpdF8xKSNHbHVjb3Npbm9sYXRlcyBhcmUgbm90IGEgc2lnbmlmaWNhbnQgcHJlZGljdG9yIG9mIGZlcm4gYWJ1bmRhbmNlIChhbHRob3VnaCB0aGUgQUlDIGlzIGFib3V0IHRoZSBzYW1lKQoKCmZpdF8xPC1nbG1tVE1CKEZlcm5+dHJlYXRtZW50KygxfGdoX2JlbmNoKSxmYW1pbHk9bmJpbm9tMixkYXRhPWRhdEZlcm4pCmZpdF8yPC1nbG1tVE1CKEZlcm5+MSsoMXxnaF9iZW5jaCksZmFtaWx5PW5iaW5vbTIsZGF0YT1kYXRGZXJuKQphbm92YShmaXRfMixmaXRfMSkKI0Zlcm4gYWJ1bmRhbmNlIGlzIHByZWRpY3RlZCBieSB0cmVhdG1lbnQuIAoKc3VtbWFyeShmaXRfMSkkY29lZgpwbG90KHJlc2lkKGZpdF8xKSkKcGxvdChyZXNpZChmaXRfMSleMikKCnN1bW1hcnkoZml0XzEpCgoKI1Blcm11dGF0aW9uIHRlc3QKZGF0UGVyVGVzdDwtZGF0RmVybgp6U3RvcmV0cmVhdEdNPC1jKCkKelN0b3JldHJlYXRNPC1jKCkKCmZvcihpIGluIDE6NTAwKXsKICAjUmFuZG9taXplIGZsYXZvbm9pZCBjb25jZW50cmF0aW9uLgogIGRhdFBlclRlc3QkdHJlYXRtZW50PC1zYW1wbGUoZGF0UGVyVGVzdCR0cmVhdG1lbnQsbGVuZ3RoKGRhdFBlclRlc3QkdHJlYXRtZW50KSxyZXBsYWNlID0gRikKCiAgI05ldyBNb2RlbCB3aXRoIHJhbmRvbWl6ZWQgdHJlYXRtZW50IGFuZCBmbGF2b25vaWRzCiAgbmV3TW9kPC11cGRhdGUoZml0XzEsZGF0YT1kYXRQZXJUZXN0KQogIAogICMgRXh0cmFjdCB0ZXN0IHN0YXRpc3RpY3MgZm9yIG1hcGxlIChNKSBhbmQgZ2FybGljIG11c3RhcmQgKGdtKSB0cmVhdG1lbnRzCiAgTXRyZWF0WnZhbDwtc3VtbWFyeShuZXdNb2QpJGNvZWZbWzFdXVszLDNdCiAgR010cmVhdFp2YWw8LXN1bW1hcnkobmV3TW9kKSRjb2VmW1sxXV1bMywyXQogIAogICNTdG9yZSB6IHZhbHVlLgogIHpTdG9yZXRyZWF0R01baV08LUdNdHJlYXRadmFsCiAgelN0b3JldHJlYXRNW2ldPC1NdHJlYXRadmFsCn0KCnN1bSh6U3RvcmV0cmVhdE0+PTIuMzE2MTgwKS9sZW5ndGgoelN0b3JldHJlYXRNKQojRXN0aW1hdGVkIHAgdmFsdWUgZm9yIHRoZSBtYXBsZSB0cmVhdG1lbnQgaXMgMC4wMS4gVGhpcyBpcyB2ZXJ5IGNsb3NlIHRvIHRoZSBhY3R1YWwgcCB2YWx1ZSBvZiAwLjAyCnN1bSh6U3RvcmV0cmVhdEdNPj0yLjIzMTU3NCkvbGVuZ3RoKHpTdG9yZXRyZWF0R00pCiNFc3RpbWF0ZWQgcCB2YWx1ZSBmb3IgdGhlIGdhcmxpYyBtdXN0YXJkIHRyZWF0bWVudCBpcyAwLiBUaGlzIGlzIGNsb3NlIHRvIHRoZSBhY3R1YWwgcCB2YWx1ZSBvZiAwLjAyCgpzdW1tYXJ5KGZpdF8xKQpgYGAKCgoKCgoKCgojVmlzdWFsaXppbmcgLS0tIHRoZSBkaXN0cmlidXRpb24gb2YgcGF0aG9nZW5zIGJ5IHRyZWF0bWVudC4gCmBgYHtyfQoKCnBsb3Q0PC1kYXQyICU+JSBkcm9wX25hKEZlcm4pICU+JSBncm91cF9ieSh0cmVhdG1lbnQpICU+JSBzdW1tYXJpemUoRmVybj1tZWFuKEZlcm4sbmEucm09VCkpCgoKdGFibGUoZGF0JGNvbXBfbnVtYmVyKQpnZ3Bsb3QocGxvdDQpKwogIGdlb21fY29sKGFlcyh4PXRyZWF0bWVudCx5PUZlcm4sZmlsbD10cmVhdG1lbnQpKSt0aGVtZV9zaW1wbGUoKSt5bGFiKCJBdmVyYWdlIEZlcm4gQWJ1bmRhbmNlXG4oZmVybnMvcG90KSIpK3hsYWIoIlRyZWF0bWVudCIpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrCiAgc2NhbGVfeF9kaXNjcmV0ZShuYW1lPSIiLGxhYmVscz1jKCJBbG9uZSIsIkdhcmxpYyBNdXN0YXJkIiwiTWFwbGUiKSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDlFNzMiLCIjNTZCNEU5IiwiI0U2OUYwMCIpLGxhYmVscz1jKCJBbG9uZSIsIkdhcmxpYyBNdXN0YXJkIiwiTWFwbGUiKSkrCiAgdGhlbWVfc2ltcGxlX211bHRpQ29sKCkrdGhlbWUoYXhpcy50aXRsZS55ID0gIGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIixtYXJnaW49bWFyZ2luKDMsMjAsMywwKSkpCiNkZXYub2ZmKCkKCmBgYAoKCgoKCgoKCgoKCgoKCiNWaXN1YWxpemluZyAtLSBlZmZlY3Qgb2YgZmxhdm9ub2lkcyBvbiBmZXJuIGFidW5kYW5jZS4gCmBgYHtyfQoKUG9pc1Nsb3BlPWZ1bmN0aW9uKHgsaW50KXsKICB5PWV4cCgoLTAuMDIzNTMgLTMuMTI0NzUpKngraW50KQogIHJldHVybih5KQp9CmV4cCgtMC42NTcxKQoKZmxhdnBsb3Q9c2VxKG1pbihkYXQkZmxhdl9Db25jLG5hLnJtID0gVCksbWF4KGRhdCRmbGF2X0NvbmMsbmEucm09VCksbGVuZ3RoLm91dCA9IDcwNykKCmZsYXZ5QTwtUG9pc1Nsb3BlKGZsYXZwbG90LC0yLjE2ODMpCmZsYXZ5TTwtUG9pc1Nsb3BlKGZsYXZwbG90LC0xLjYwNTQ2LTIuODE0NTApCmZsYXZ5R008LVBvaXNTbG9wZShmbGF2cGxvdCwtMi4xNjgzLTAuMjc4NikKCgojdGlmZigiRGVmZW5jZV9GaWd1cmVzL0ZsYXZvbm9pZEZlcm4udGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTEwLCBoZWlnaHQ9NiwgcmVzPTMwMCkKZ2dwbG90KGRhdCkrCiAgZ2VvbV9wb2ludChhZXMoeT1GZXJuLHg9Zmxhdl9Db25jLGNvbG91cj10cmVhdG1lbnQpKSt0aGVtZV9zaW1wbGUoKSsKICMgZ2VvbV9wYXRoKHg9ZmxhdnBsb3QseT1mbGF2eUEsc2l6ZT0xLGNvbG91cj0iIzAwOUU3MyIpCiAgI2dlb21fcGF0aCh4PWZsYXZwbG90LHk9ZmxhdnlHTSxzaXplPTEsY29sb3VyPSIjNTZCNEU5IikKICBnZW9tX3BhdGgoeD1mbGF2cGxvdCx5PWZsYXZ5TSxzaXplPTEsY29sb3VyPSIjRTY5RjAwIikrCiAgICAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzPWMoIiMwMDlFNzMiLCIjNTZCNEU5IiwiI0U2OUYwMCIpLGxhYmVscz1jKCJBbG9uZSIsIkdhcmxpYyBNdXN0YXJkIiwiTWFwbGUiKSkrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1jKDAsNSwxMCwxNSwyMCwyNSwzMCwzNSw0MCkpKwogIHlsYWIoIkZlcm4gQWJ1bmRhbmNlIikrCnhsYWIoYnF1b3RlKGJvbGQoIltUb3RhbCBGbGF2b25vaWRdICIgKG1nL21sKSkpKQojZGV2Lm9mZigpCgpgYGAKCkhvdyBjYW4gd2Uga25vdyB0aGF0IGhlYWx0aHkgcGxhbnRzIGRvbnQganVzdCBleGhpYml0IG1vcmUgc2Vjb25kYXJ5IGNvbXBvdW5kcyBhbmQgbm90IHRoYXQgdGhvc2Ugd2l0aCBtb3JlIHNlY29uZGFyeSBjb21wb3VuZHMgYXJlIGhlYWx0aGllcj8KCgoKCgo=